# How to Use Trivy in CI/CD Pipelines: GitHub Actions, GitLab CI, and Jenkins Integration Guide

> Learn how to integrate Trivy into your CI/CD pipelines. This guide covers GitHub Actions, GitLab CI, and Jenkins for automated vulnerability scanning in every commit.

- Repository: [Aqua Security/trivy](https://github.com/aquasecurity/trivy)
- Tags: how-to-guide
- Published: 2026-03-23

---

**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:

1. **Install or pull Trivy** – via GitHub Action, `wget` download in GitLab, or Docker image in Jenkins.
2. **Execute the scan** – invoking commands like `trivy image <image>`, `trivy fs <path>`, or `trivy config <dir>`.
3. **Evaluate the exit code** – `0` indicates no findings or filtered severities; non-zero triggers pipeline failure.
4. **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`](https://github.com/aquasecurity/trivy/blob/main/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`](https://github.com/aquasecurity/trivy/blob/main/.github/workflows/trivy.yml)) that checks out your repository and invokes the action from `aquasecurity/trivy-action@master`:

```yaml
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`](https://github.com/aquasecurity/trivy/blob/main/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`](https://github.com/aquasecurity/trivy/blob/main/docs/tutorials/integrations/gitlab-ci.md):

```yaml
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:

```groovy
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 `--severity` flags (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@master` to 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.tpl` templates to generate native GitLab security reports with proper artifact caching.
- **Jenkins**: Execute the `aquasec/trivy` Docker 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.