DevSecOps - Kubernetes DevOps & Security

DevSecOps Pipeline

Demo Trivy Image Scan Docker 1

In this tutorial, we'll use Trivy—the open-source vulnerability scanner from Aqua Security—to analyze a base image defined in your Dockerfile. Trivy can operate in standalone or client-server mode and supports three artifact types:

  • Container images
  • File systems
  • Git repositories

Throughout this guide, we’ll focus on scanning container images with Trivy’s Docker image.

Note

Refer to the official Trivy Documentation for detailed information on supported targets and scanning modes.

The image shows a webpage for Trivy, a vulnerability scanner for containers and other artifacts, with a menu on the left and an abstract section describing its features. There is also a diagram illustrating different targets, artifacts, and modes.


Installation

You can install Trivy as a native binary or pull the official Docker image.

RPM-based Systems

sudo tee /etc/yum.repos.d/trivy.repo <<EOF
[trivy]
name=Trivy repository
baseurl=https://aquasecurity.github.io/trivy-repo/rpm/releases/$releasever/$basearch/
gpgcheck=0
enabled=1
EOF

sudo yum -y update
sudo yum -y install trivy

Debian-based Systems

sudo apt-get update
sudo apt-get install -y wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" \
  | sudo tee /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install -y trivy

Docker Image

docker pull aquasec/trivy:0.18.3

Trivy Scanning Targets & Modes

Artifact TypeDescriptionExample Command
Container ImageDocker or OCI imagestrivy image python:3.4-alpine
File SystemLocal directory scantrivy fs /path/to/project
Git RepositoryRemote or local Git repository scantrivy repo https://github.com/aquasecurity/trivy
ModeDescription
StandaloneLocal DB, no server required
Client-serverCentralized vulnerability database (gRPC API)

Quick Scan with Trivy Docker Image

Scan the python:3.4-alpine image and cache the vulnerability database locally:

docker run --rm \
  -v $HOME/Library/Caches:/root/.cache/ \
  aquasec/trivy:0.18.3 \
  python:3.4-alpine

Sample output:

2021-06-18T15:04:39.306Z    INFO  Detected OS: alpine
2021-06-18T15:04:39.306Z    INFO  Detecting Alpine vulnerabilities...
2021-06-18T15:04:39.306Z    WARN  This OS version is no longer supported: alpine 3.9.2

Total: 37 (UNKNOWN: 0, LOW: 4, MEDIUM: 16, HIGH: 13, CRITICAL: 4)
...

Note

Mounting a cache directory speeds up repeated scans by storing the vulnerability database locally.


Filtering by Severity

To report only CRITICAL vulnerabilities:

docker run --rm \
  -v $HOME/Library/Caches:/root/.cache/ \
  aquasec/trivy:0.18.3 \
  --severity CRITICAL \
  python:3.4-alpine

Sample output:

Total: 4 (CRITICAL: 4)
...

Warning

By default, Trivy exits with code 0 even if vulnerabilities are found. Use --exit-code to enforce build failures in CI/CD.


Using Custom Exit Codes

Fail CI pipelines on CRITICAL issues:

docker run --rm \
  -v $HOME/Library/Caches:/root/.cache/ \
  aquasec/trivy:0.18.3 \
  --severity CRITICAL \
  --exit-code 1 \
  python:3.4-alpine

echo $?  # Returns 1 if any CRITICAL vulnerabilities are detected

Ignore LOW severity issues while still failing on HIGH+:

docker run --rm \
  -v $HOME/Library/Caches:/root/.cache/ \
  aquasec/trivy:0.18.3 \
  --severity LOW \
  --exit-code 0 \
  python:3.4-alpine

echo $?  # Always returns 0, even if LOW or MEDIUM are found

Integrating Trivy in a Jenkins Pipeline

Scan the base image before building and pushing Docker artifacts. Below is a sample declarative Jenkinsfile:

pipeline {
  agent any

  stages {
    stage('SonarQube - SAST') {
      steps {
        withSonarQubeEnv('SonarQube') {
          sh "mvn sonar:sonar \
             -Dsonar.projectKey=numeric-application \
             -Dsonar.host.url=http://devsecops-demo.eastus.cloudapp.azure.com:9000"
        }
      }
      post {
        always {
          timeout(time: 2, unit: 'MINUTES') {
            script { waitForQualityGate abortPipeline: true }
          }
        }
      }
    }

    stage('Vulnerability Scan - Docker') {
      steps {
        parallel(
          'Dependency Scan': {
            sh "mvn dependency-check:check"
          },
          'Trivy Scan': {
            sh "bash trivy-docker-image-scan.sh"
          }
        )
      }
    }

    stage('Docker Build and Push') {
      steps {
        withDockerRegistry([credentialsId: 'docker-hub', url: '']) {
          sh 'docker build -t siddharth67/numeric-app:$GIT_COMMIT .'
          sh 'docker push siddharth67/numeric-app:$GIT_COMMIT'
        }
      }
    }

    stage('Kubernetes Deployment - DEV') {
      steps {
        // Add deployment steps here
      }
    }
  }
}

Creating the Trivy Scan Script

Add a file named trivy-docker-image-scan.sh at the repository root:

#!/bin/bash

# Extract base image from the first line of Dockerfile
dockerImageName=$(awk 'NR==1 {print $2}' Dockerfile)
echo "Scanning image: $dockerImageName"

# Scan HIGH severity (no failure)
docker run --rm -v $WORKSPACE:/root/.cache/ \
  aquasec/trivy:0.17.2 -q image \
  --exit-code 0 --severity HIGH --light \
  $dockerImageName

# Scan CRITICAL severity (fail on detection)
docker run --rm -v $WORKSPACE:/root/.cache/ \
  aquasec/trivy:0.17.2 -q image \
  --exit-code 1 --severity CRITICAL --light \
  $dockerImageName

exit_code=$?
echo "Exit code: $exit_code"

if [ $exit_code -eq 1 ]; then
  echo "Image scanning failed. CRITICAL vulnerabilities found."
  exit 1
else
  echo "Image scanning passed. No CRITICAL vulnerabilities found."
  exit 0
fi

Make the script executable:

chmod +x trivy-docker-image-scan.sh

Verifying in Jenkins

Commit and push your changes. Trigger a Jenkins build to see two parallel steps under the Vulnerability Scan – Docker stage:

The image shows a GitHub Desktop interface with no local changes and options to push commits, open the repository in an editor, view files in Explorer, or open the repository on GitHub. A profile picture is visible in the top right corner.

The image shows a Jenkins dashboard with a list of projects, including "checking-versions" and "devsecops-numeric-application," displaying their last success, last failure, and duration. The interface includes navigation options on the left and a user profile icon on the top right.

The image shows a Jenkins pipeline dashboard with a stage view of a build process, including stages like SCM checkout, Maven build, unit tests, and vulnerability scans. It also features graphs for coverage and dependency-check trends.

The image shows a Jenkins dashboard displaying a list of pipeline builds for a project named "devsecops-numeric-application," with their statuses, run numbers, commit messages, durations, and completion times.

The image shows a Jenkins dashboard with a pipeline stage view, including build history and error logs. It displays various stages of a build process, some of which have failed, indicated by red highlights.


Watch Video

Watch video content

Previous
Trivy Basics