How to Use Trivy in CI/CD Pipelines: GitHub Actions, GitLab CI, and Jenkins Integration Guide
Trivy integrates into CI/CD pipelines by executing its single binary or Docker image within workflow jobs, scanning targets on every commit, and failing builds based on configured severity thresholds.
The aquasecurity/trivy repository provides native integrations and documented patterns for embedding vulnerability scanning into automated build workflows. Whether you are securing container images, filesystems, or Infrastructure-as-Code (IaC) files, Trivy's lightweight architecture allows it to run as a standalone step that pulls vulnerability databases, performs the scan, and exits with a status code that CI systems can interpret as pass or fail.
Understanding Trivy's CI/CD Architecture
At its core, Trivy operates as a zero-dependency binary (or container image) that executes four deterministic steps in pipeline contexts:
- Install or pull Trivy – via GitHub Action,
wgetdownload in GitLab, or Docker image in Jenkins. - Execute the scan – invoking commands like
trivy image <image>,trivy fs <path>, ortrivy config <dir>. - Evaluate the exit code –
0indicates no findings or filtered severities; non-zero triggers pipeline failure. - Publish the report – SARIF for GitHub Code Scanning, GitLab Container-Scanning JSON, or archived artifacts for Jenkins review.
This consistent pattern is documented in docs/ecosystem/cicd.md, which outlines the official integration paths for multiple platforms.
GitHub Actions Integration
The official trivy-action wraps the Trivy binary in a reusable GitHub Action, automating the installation and execution steps.
Configuring the Security Scan Workflow
Create a workflow file (e.g., .github/workflows/trivy.yml) that checks out your repository and invokes the action from aquasecurity/trivy-action@master:
name: Security Scan
on:
push:
branches: [ main ]
jobs:
trivy-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Trivy vulnerability scan
uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:latest
format: sarif
output: trivy-results.sarif
- name: Upload SARIF report
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: trivy-results.sarif
The image-ref parameter specifies the target container image, while format: sarif generates output compatible with GitHub's security dashboard. The reference documentation in docs/tutorials/integrations/github-actions.md provides additional configuration options for scanning filesystems and repositories.
GitLab CI Integration
Trivy supports GitLab CI through both the built-in Container-Scanning template and custom job definitions that offer granular control over scan parameters and caching.
Using the Official Template
GitLab includes Trivy in its managed Container-Scanning template, which automatically produces a container_scanning report artifact visible in the GitLab Security Dashboard. Alternatively, implement a custom job as defined in docs/tutorials/integrations/gitlab-ci.md:
stages:
- test
trivy:
stage: test
image: docker:stable
services:
- name: docker:dind
entrypoint: ["env", "-u", "DOCKER_HOST"]
command: ["dockerd-entrypoint.sh"]
variables:
DOCKER_HOST: tcp://docker:2375/
TRIVY_NO_PROGRESS: "true"
TRIVY_CACHE_DIR: ".trivycache/"
before_script:
- |
export TRIVY_VERSION=$(wget -qO - "https://api.github.com/repos/aquasecurity/trivy/releases/latest" \
| grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
- wget --no-verbose https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz \
-O - | tar -zxvf -
script:
- ./trivy image --exit-code 0 --format template \
--template "@/contrib/gitlab.tpl" -o gl-container-scanning-report.json $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- ./trivy image --exit-code 1 --severity CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
artifacts:
reports:
container_scanning: gl-container-scanning-report.json
cache:
paths:
- .trivycache/
This configuration downloads the latest Trivy release dynamically, uses the GitLab-specific template (@/contrib/gitlab.tpl) for report formatting, and separates the reporting scan (--exit-code 0) from the enforcement scan (--exit-code 1 --severity CRITICAL) to ensure pipelines fail only on critical vulnerabilities while still capturing all findings for review.
Jenkins Integration
While no official Jenkins plugin exists in the aquasecurity/trivy repository, you can integrate Trivy into Declarative Pipelines by executing the Docker image directly on your Jenkins agents.
Docker-Based Pipeline Scanning
Mount the Docker socket to allow Trivy to access the local image daemon, then archive the results and parse them to enforce security gates:
pipeline {
agent any
stages {
stage('Trivy Scan') {
steps {
sh 'docker pull aquasec/trivy:latest'
sh '''
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image --exit-code 0 --severity HIGH \
myapp:latest > trivy-report.txt
'''
archiveArtifacts artifacts: 'trivy-report.txt', onlyIfSuccessful: false
script {
def exitCode = sh script: "grep -q 'HIGH' trivy-report.txt && echo 1 || echo 0", returnStatus: true
if (exitCode != 0) {
error "Trivy detected HIGH severity vulnerabilities."
}
}
}
}
}
}
This approach pulls the latest aquasec/trivy image, scans the target image with --severity HIGH threshold, archives the text report for manual inspection, and programmatically fails the build if high-severity vulnerabilities are detected.
Controlling Pipeline Behavior with Exit Codes
All three platforms utilize Trivy's exit code logic to control pipeline flow:
--exit-code 0– Always returns success; use this when you want to generate reports without failing the build.--exit-code 1– Returns failure if vulnerabilities are found; combine with--severityflags (e.g.,CRITICAL,HIGH) to fail only on specific risk levels.
This mechanism allows you to implement break-glass patterns where the pipeline generates security artifacts for every build but only blocks deployment for severe findings.
Summary
- GitHub Actions: Use
aquasecurity/trivy-action@masterto scan images or filesystems and upload SARIF results directly to GitHub Code Scanning. - GitLab CI: Leverage the Container-Scanning template or custom jobs with
@/contrib/gitlab.tpltemplates to generate native GitLab security reports with proper artifact caching. - Jenkins: Execute the
aquasec/trivyDocker image with socket mounts, archive text/JSON reports, and use shell scripts to parse results and enforce build failures. - Common pattern: Install Trivy, run the scan with appropriate severity filters, check exit codes, and publish reports in platform-native formats.
Frequently Asked Questions
How do I prevent Trivy from failing my CI pipeline on low-severity vulnerabilities?
Configure the --severity flag to specify which vulnerability levels should trigger a non-zero exit code. For example, use --severity HIGH,CRITICAL to fail only on high and critical findings, while allowing the scan to pass (exit code 0) for low and medium vulnerabilities. You can also run two separate scans: one with --exit-code 0 for reporting all findings, and one with --exit-code 1 --severity CRITICAL for enforcement.
Can Trivy scan source code before I build a container image?
Yes. Use trivy fs <path> to scan the filesystem and repository for vulnerabilities in application dependencies and IaC misconfigurations. In GitHub Actions, set scan-type: 'fs' in the trivy-action inputs. For GitLab CI and Jenkins, replace the trivy image command with trivy fs . to analyze the checked-out source code prior to image build steps.
Where does Trivy store its vulnerability database in CI environments?
Trivy downloads vulnerability databases to a local cache directory, which defaults to a system temp folder. In ephemeral CI runners, define the TRIVY_CACHE_DIR environment variable (e.g., TRIVY_CACHE_DIR: ".trivycache/") and configure your pipeline's cache mechanism to preserve this directory between jobs. This prevents redundant database downloads and speeds up subsequent scans, as demonstrated in the GitLab CI example.
What report formats should I use for different CI platforms?
SARIF (Static Analysis Results Interchange Format) is optimal for GitHub Actions because GitHub Code Scanning natively consumes it. GitLab Container-Scanning JSON (produced via the @/contrib/gitlab.tpl template) is required for GitLab's security dashboard integration. For Jenkins, JSON or plain text formats work best, allowing you to archive artifacts and parse results using shell commands or the Jenkins Warnings Next Generation plugin.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →