CI/CD Security Scanning with Trivy (Complete DevSecOps Guide)

cicd security scanning trivy custom-trivy-featured.png

Our Harbor guide enabled vulnerability scanning at the registry — after an image is already pushed. DevSecOps means catching the same problems earlier, in the pipeline, before a vulnerable image or misconfigured Terraform file ever reaches production. Trivy is a single, fast, open-source scanner that covers both: container image vulnerabilities and infrastructure-as-code misconfigurations, in one tool.

This guide scans an image locally, sets severity thresholds that fail a build, adds Trivy to a CI pipeline, scans Terraform for misconfigurations, and manages false positives without disabling the check entirely.

Step 1: What “Shift-Left” Security Actually Means

Catching a critical vulnerability after an image is deployed to production means an incident response process, an emergency patch, and possibly downtime. Catching the same vulnerability in a pull request means a comment on the PR and a rebuild before anything ships. “Shift-left” just means moving that detection as early in the pipeline as possible — Trivy’s speed (seconds, not minutes, for most images) is what makes running it on every single commit practical.

What shift-left security means in CI/CD pipelines
Step 1: What “Shift-Left” Security Actually Means

Step 2: Install Trivy

Install via your package manager or the official install script: curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh. Confirm with trivy --version. Trivy needs no server or database setup — it downloads its vulnerability database on first run and caches it locally.

Installing Trivy vulnerability scanner
Step 2: Install Trivy

Step 3: Scan a Container Image

trivy image registry.example.com/myproj/app:1.0 scans every layer of the image against Trivy’s vulnerability database and prints a summary table by severity (CRITICAL, HIGH, MEDIUM, LOW). Run this against an image you already pushed to your Harbor registry to get a feel for typical findings before wiring it into automation.

Scanning a container image for vulnerabilities with Trivy
Step 3: Scan a Container Image

Step 4: Set a Severity Threshold to Fail the Build

trivy image --severity CRITICAL --exit-code 1 app:1.0 only reports CRITICAL findings and exits non-zero if any are found — this exit code is what a CI pipeline actually checks to decide pass/fail. Starting with CRITICAL-only is a reasonable first gate; tightening to also fail on HIGH is a natural next step once the team is used to acting on scan results.

Setting Trivy severity threshold to fail CI build on critical vulnerabilities
Step 4: Set a Severity Threshold to Fail the Build

Step 5: Add Trivy to a CI Pipeline

In a GitLab CI or Jenkins pipeline (building on our GitLab Runner or Jenkins setup), add a stage that runs after the image build step: build the image, run trivy image --severity CRITICAL,HIGH --exit-code 1 $IMAGE_TAG, and only proceed to push/deploy stages if that step succeeds. This makes the scan a required gate, not an optional check someone has to remember to run.

Integrating Trivy scan into GitLab CI or Jenkins pipeline
Step 5: Add Trivy to a CI Pipeline

Step 6: Scan Infrastructure as Code

Trivy also scans IaC for misconfigurations, not just container images: trivy config ./terraform/ against a Terraform project (like our Proxmox Terraform setup) flags issues like open security groups, unencrypted storage, or missing logging — the same category of misconfiguration tools like tfsec specialize in, covered in a companion guide on this blog.

Scanning Terraform infrastructure as code with Trivy config
Step 6: Scan Infrastructure as Code

Step 7: Manage False Positives With .trivyignore

Not every finding is actionable immediately — a CVE with no available fix yet, or an accepted risk documented elsewhere. Add specific CVE IDs to a .trivyignore file in the project root, one per line, ideally with a comment explaining why (CVE-2023-99999 # accepted risk, see ticket OPS-412) so the exception has a paper trail instead of silently suppressing findings forever.

Managing Trivy false positives with .trivyignore file
Step 7: Manage False Positives With .trivyignore

Step 8: Avoid Duplicating Harbor’s Own Scanning

If your registry already scans on push (our Harbor guide enabled Trivy there too), running the identical scan again in CI is redundant work, not extra safety. A common pattern: run the fast CRITICAL-only gate in CI to fail fast before a push even happens, and rely on Harbor’s registry-side scan (with the full severity range) as the ongoing source of truth for what’s actually sitting in the registry.

Avoiding duplicate scanning between CI Trivy and Harbor registry
Step 8: Avoid Duplicating Harbor’s Own Scanning

Command reference

# Scan an image
trivy image myapp:1.0

# Fail build on critical findings
trivy image --severity CRITICAL --exit-code 1 myapp:1.0

# Scan Terraform/IaC
trivy config ./terraform/

# .trivyignore
echo 'CVE-2023-99999  # accepted risk, ticket OPS-412' >> .trivyignore

Related tutorials

Terminal screenshots are original illustrations created for Gnome IT Solutions (blog.gnomeitsolutions.com).