How to Set Up Jenkins for Container Vulnerability Scanning with Trivy

How to Set Up Jenkins for Container Vulnerability Scanning with Trivy

Of all the security tools I’ve integrated into Jenkins pipelines, Trivy is by far the easiest to get started with, and it’s the one I recommend first to any team just beginning their container security journey. It’s open source, fast, requires no server setup, and runs as a single binary or container — no licensing negotiations, no complex API authentication flows. I added Trivy to a pipeline in an afternoon the first time I tried it, and it’s been part of every container-based project I’ve worked on since.

This guide covers everything from installing Trivy, running it inside Jenkins, scanning both images and infrastructure-as-code, and gating deployments based on findings.

Why Trivy for Container Security

Trivy, built by Aqua Security, is a comprehensive open-source scanner that detects:

  • OS package vulnerabilities (Alpine, Debian, Ubuntu, CentOS, etc.)
  • Application dependency vulnerabilities (npm, pip, Maven, Go modules, and more)
  • Misconfigurations in Dockerfiles, Kubernetes manifests, and Terraform files
  • Exposed secrets accidentally baked into image layers
  • License compliance issues in dependencies

Because it runs as a lightweight CLI tool, it fits naturally into a Jenkins pipeline step without needing a separate scanning server or complex API polling like some enterprise DAST tools require.

Jenkins Architecture Context

Trivy scans typically run right after the docker build step and before docker push, catching vulnerable base images or dependencies before they ever reach a registry. Because Trivy is just a CLI, Jenkins invokes it directly via sh steps — there’s no REST API polling loop needed, which makes this one of the simplest security integrations to build and maintain.

Prerequisites

  • Docker installed on the Jenkins agent (or a Docker-in-Docker/Kubernetes agent setup).
  • Trivy installed on the agent, or available as a container image (aquasec/trivy).
  • No license or API key required for the open-source version.

Step 1: Install Trivy on the Jenkins Agent

On a Debian/Ubuntu-based Jenkins agent:

sudo apt-get install 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 -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy

Alternatively, skip installation entirely and just run Trivy as a Docker container, which is often cleaner for CI environments:

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image myapp:latest

Step 2: Basic Jenkinsfile with Trivy Image Scanning

pipeline {
    agent any

    environment {
        IMAGE_NAME = 'myapp'
        IMAGE_TAG = "${env.BUILD_NUMBER}"
    }

    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }

        stage('Build Docker Image') {
            steps {
                sh "docker build -t ${IMAGE_NAME}:${IMAGE_TAG} ."
            }
        }

        stage('Trivy Vulnerability Scan') {
            steps {
                sh """
                    trivy image \
                        --severity HIGH,CRITICAL \
                        --exit-code 1 \
                        --format table \
                        --output trivy-report.txt \
                        ${IMAGE_NAME}:${IMAGE_TAG}
                """
            }
        }

        stage('Push Image') {
            steps {
                sh "docker push ${IMAGE_NAME}:${IMAGE_TAG}"
            }
        }
    }

    post {
        always {
            archiveArtifacts artifacts: 'trivy-report.txt', allowEmptyArchive: true
        }
        failure {
            mail to: 'devops-team@example.com',
                 subject: "Trivy Scan Failed: ${IMAGE_NAME}:${IMAGE_TAG}",
                 body: "High/Critical vulnerabilities detected. See attached report."
        }
    }
}

The --exit-code 1 flag is what makes Trivy actually fail the Jenkins build when it finds vulnerabilities at or above the specified severity — without it, Trivy just reports and exits 0 regardless of findings.

Step 3: JSON Output for Programmatic Gating

For more nuanced gating logic (say, allowing a small number of medium vulnerabilities but blocking on any critical), use JSON output and parse it with readJSON:

stage('Trivy Scan with Custom Gating') {
    steps {
        sh """
            trivy image --format json --output trivy-results.json ${IMAGE_NAME}:${IMAGE_TAG}
        """
        script {
            def results = readJSON file: 'trivy-results.json'
            def criticalCount = 0
            results.Results.each { result ->
                result.Vulnerabilities?.each { vuln ->
                    if (vuln.Severity == 'CRITICAL') {
                        criticalCount++
                    }
                }
            }
            if (criticalCount > 0) {
                error "Found ${criticalCount} CRITICAL vulnerabilities. Failing build."
            } else {
                echo "No critical vulnerabilities found."
            }
        }
    }
}

Step 4: Using the Trivy Jenkins Plugin

There’s also an official Trivy plugin for Jenkins that provides built-in report visualization:

stage('Trivy Scan') {
    steps {
        trivy(
            image: "${IMAGE_NAME}:${IMAGE_TAG}",
            severity: 'HIGH,CRITICAL',
            format: 'table'
        )
    }
}

(Note: plugin availability and exact syntax may vary by version — check the plugin page for the latest usage details.)

Scanning Dockerfiles and IaC for Misconfigurations

Trivy isn’t limited to scanning built images — it can also scan your Dockerfile and Kubernetes/Terraform manifests directly for misconfigurations before you even build:

stage('Trivy Config Scan') {
    steps {
        sh 'trivy config --severity HIGH,CRITICAL --exit-code 1 .'
    }
}

This catches issues like running containers as root, missing resource limits in Kubernetes manifests, or overly permissive Terraform security group rules — all before the image is even built.

Scanning for Exposed Secrets

Trivy also includes a secret-scanning mode, useful for catching accidentally committed API keys or credentials baked into image layers:

stage('Trivy Secret Scan') {
    steps {
        sh "trivy image --scanners secret ${IMAGE_NAME}:${IMAGE_TAG}"
    }
}

Integrating with Git and GitHub

Report scan status directly on pull requests:

post {
    failure {
        githubNotify status: 'FAILURE', context: 'trivy-scan', description: 'Critical vulnerabilities found'
    }
    success {
        githubNotify status: 'SUCCESS', context: 'trivy-scan', description: 'No critical vulnerabilities'
    }
}

Integrating with Kubernetes

For clusters already running workloads, Trivy Operator can continuously scan images running in your cluster, complementing the CI-time scan with runtime visibility:

apiVersion: aquasecurity.github.io/v1alpha1
kind: VulnerabilityReport

Jenkins-triggered scans catch issues before deployment; the Trivy Operator catches new CVEs discovered after deployment for images that haven’t changed but whose vulnerability databases have been updated.

Integrating with Maven and Application Dependencies

Beyond container images, Trivy can scan a filesystem directly for language-specific dependency vulnerabilities, useful for Java/Maven projects even before containerization:

stage('Trivy Filesystem Scan') {
    steps {
        sh 'trivy fs --severity HIGH,CRITICAL --exit-code 1 .'
    }
}

This catches vulnerable dependencies declared in pom.xml, package.json, requirements.txt, and similar manifest files.

Monitoring and Reporting

For teams wanting a persistent, searchable history of scan results beyond individual build artifacts, consider piping Trivy JSON output into a centralized dashboard like DefectDojo or Elastic/Kibana. This gives you trend analysis across builds — “are we introducing more vulnerabilities over time, or fewer?” — which is hard to answer from individual Jenkins console logs alone.

Troubleshooting Common Issues

  • Trivy database download failures — Trivy downloads a vulnerability database on first run; if your Jenkins agents have restricted network access, mirror the database internally or use --skip-db-update with a pre-cached DB.
  • Slow scans on large images — cache the Trivy vulnerability database between builds using a persistent volume or Docker volume mount to avoid re-downloading it every run.
  • Too many findings on legacy images — start with --severity CRITICAL only, then progressively tighten to HIGH,CRITICAL as your team works through the backlog.

Best Practices

  • Scan images immediately after build, before pushing to any registry.
  • Use --exit-code 1 combined with --severity to enforce real gating, not just reporting.
  • Cache the Trivy vulnerability database locally to speed up repeated scans.
  • Combine image scanning with trivy config for Dockerfile/Kubernetes/Terraform misconfiguration checks.
  • Run trivy fs scans early for language dependency vulnerabilities, even before a container image exists.
  • Pair CI-time scanning with a runtime tool (like Trivy Operator) for ongoing visibility into deployed workloads.

FAQs

Is Trivy really free for commercial use? Yes, Trivy is fully open source under the Apache 2.0 license, with no licensing fees for commercial or enterprise use.

Can Trivy scan private registries? Yes, Trivy supports scanning images directly from private registries (ECR, GCR, Docker Hub private repos, Harbor) given proper registry authentication.

How often is the Trivy vulnerability database updated? Trivy’s vulnerability database updates multiple times daily, pulling from sources like NVD, GitHub Security Advisories, and various OS vendor security trackers.

Does Trivy replace the need for a DAST tool like Burp Suite or Acunetix? No — Trivy focuses on known vulnerabilities in packages/dependencies and misconfigurations (a form of SCA/IaC scanning), while DAST tools test running applications for exploitable behavior. They’re complementary, not interchangeable.

Summary

Trivy is one of the fastest ways to add meaningful, zero-cost container security scanning into a Jenkins pipeline. From scanning built images for known CVEs, to catching Dockerfile misconfigurations and exposed secrets, it slots cleanly into the build-before-push stage of any containerized CI/CD workflow. Combined with severity-based gating and artifact archiving, it gives your team continuous, low-friction visibility into the security posture of every image you ship.

References

  • Trivy Official Documentation: https://aquasecurity.github.io/trivy/latest/
  • Trivy GitHub Repository: https://github.com/aquasecurity/trivy
  • Trivy Jenkins Plugin: https://plugins.jenkins.io/trivy/
  • Trivy Operator for Kubernetes: https://aquasecurity.github.io/trivy-operator/latest/
Total
1
Shares

Leave a Reply

Previous Post
How to Use Jenkins with Cypress for End-to-End Testing

How to Use Jenkins with Cypress for End-to-End Testing

Next Post
How to Set Up Jenkins for Security Scanning with Nessus

How to Set Up Jenkins for Security Scanning with Nessus

Related Posts