Trivy for Enterprise DevSecOps: Architecture, Deployment, and Hardening Guide
Prerequisites
- Familiarity with containers and OCI registries
- Working knowledge of CI/CD pipelines
Steps
Trivy is a lightweight but enterprise-capable security scanner for containers, filesystems, Git repositories, Kubernetes, and infrastructure as code. This guide explains how to deploy, operationalize, and harden Trivy in CI/CD and platform engineering environments.
Overview
Trivy is an open-source security scanner from Aqua Security designed to detect vulnerabilities, misconfigurations, secrets, and software licenses across container images, filesystems, Git repositories, Kubernetes clusters, and IaC templates. Enterprises use it because it is fast, easy to automate, and broad in scope, allowing security teams to standardize scanning across build pipelines and runtime-adjacent workflows.
In practice, Trivy is commonly used to:
- Scan container images in CI before promotion
- Validate Terraform, Kubernetes YAML, and Helm charts
- Detect embedded secrets in source repositories
- Generate SBOMs and support compliance evidence
- Enforce policy gates with non-zero exit codes
Architecture
Trivy has a simple architecture with flexible deployment options.
Core components
- Trivy CLI: main scanner for images, repos, fs, config, k8s, and sbom
- Vulnerability DB: downloaded locally or served remotely; includes OS and language package advisories
- Java DB: supplemental metadata for Java package analysis
- Misconfiguration checks: built-in policies for Kubernetes, Dockerfile, Terraform, and cloud configs
- Cache: local cache for DBs and scan artifacts to improve performance
Deployment models
- Developer workstation: local scans during development
- CI/CD runner: ephemeral execution in GitHub Actions, GitLab CI, Jenkins, or Azure DevOps
- Centralized service: Trivy server/client mode for shared DB access and reduced internet egress
- Air-gapped enterprise: mirrored DB artifacts and controlled update workflows
Data flow
- Trivy updates the vulnerability database.
- The scanner pulls image metadata or parses source files.
- Packages, manifests, and config objects are normalized.
- Findings are matched against vulnerability and policy data.
- Results are output as table, JSON, SARIF, CycloneDX, or SPDX.
Implementation Guide
1. Install Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
trivy --version
2. Pre-download databases for CI stability
trivy image --download-db-only
trivy image --download-java-db-only
3. Create enterprise config
cache:
dir: /var/lib/trivy
format: table
exit-code: 1
severity:
- CRITICAL
- HIGH
ignore-unfixed: true
scanners:
- vuln
- secret
- misconfig
timeout: 10m
Save as .trivy.yaml.
4. Scan a container image
trivy image --config .trivy.yaml --input /tmp/image.tar
# or directly from registry
trivy image --config .trivy.yaml registry.example.com/payments/api:1.4.7
5. Scan IaC and repository content
trivy config ./infra
trivy fs --scanners vuln,secret,misconfig .
6. Produce machine-readable output for pipelines
trivy image --format sarif --output trivy-results.sarif registry.example.com/payments/api:1.4.7
trivy image --format cyclonedx --output sbom.cdx.json registry.example.com/payments/api:1.4.7
7. Run in client/server mode
Start server:
trivy server --listen 0.0.0.0:4954
Run client:
trivy client --remote http://trivy.internal.example.com:4954 image registry.example.com/payments/api:1.4.7
Code Examples
Example 1: Bash policy gate in CI
#!/usr/bin/env bash
set -euo pipefail
IMAGE="registry.example.com/payments/api:${GIT_COMMIT}"
trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 "$IMAGE"
trivy image --format json --output trivy-report.json "$IMAGE"
Example 2: GitHub Actions workflow
name: trivy-scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: aquasecurity/trivy-action@0.24.0
with:
scan-type: fs
scan-ref: .
scanners: vuln,secret,misconfig
severity: HIGH,CRITICAL
ignore-unfixed: true
exit-code: '1'
Example 3: Python parse of JSON findings
import json
with open("trivy-report.json", "r", encoding="utf-8") as f:
report = json.load(f)
critical = 0
for result in report.get("Results", []):
for vuln in result.get("Vulnerabilities", []) or []:
if vuln.get("Severity") == "CRITICAL":
critical += 1
print({"critical_findings": critical})
if critical > 0:
raise SystemExit(1)
Security Hardening
- Store cache in a restricted path such as
/var/lib/trivywith root or dedicated service ownership. - Use client/server mode to centralize DB access and reduce uncontrolled outbound traffic.
- Pin Trivy versions in CI to avoid untested scanner changes.
- Restrict registry credentials to read-only scope.
- Encrypt artifact storage for SARIF, SBOM, and JSON outputs because findings may expose package and path metadata.
- In Kubernetes, run scans with a dedicated service account and least-privilege RBAC.
- For air-gapped environments, mirror DB updates through a signed internal process.
Comparison
| Feature | Trivy | Snyk Container | Prisma Cloud |
|---|---|---|---|
| Pricing | Open-source; enterprise support via vendors | Commercial subscription | Commercial platform pricing |
| Deployment | CLI, CI, server mode, air-gapped friendly | SaaS-first with CLI and integrations | SaaS/platform-centric with broad CNAPP features |
| Scalability | High for distributed CI and centralized server patterns | Strong for developer-centric SaaS workflows | Strong for large multi-cloud enterprises |
| Security scope | Vulns, secrets, misconfig, licenses, SBOM | Vulns, code, container, IaC | Container, cloud posture, runtime, IaC |
| Best fit | Cost-efficient DevSecOps standardization | Developer remediation workflows | Broad cloud security platform consolidation |
Troubleshooting
Error 1: Database download timeout
Log sample:
2025-02-11T08:14:22Z FATAL init error: DB error: failed to download vulnerability DB: OCI artifact error: Get "https://ghcr.io/v2/": context deadline exceeded
Fix: pre-download DBs in a scheduled job, increase --timeout, or use internal proxy/server mode.
Error 2: Unauthorized registry access
Log sample:
2025-02-11T09:02:41Z ERROR image scan error: failed to inspect the image (registry.example.com/payments/api:1.4.7): unauthorized: authentication required
Fix: authenticate with docker login, validate robot account scope, and ensure CI runner can access the private registry.
Error 3: Misconfiguration scan parse failure
Log sample:
2025-02-11T09:17:03Z WARN Failed to parse Terraform file file_path=infra/main.tf error="hcl syntax error: Invalid expression"
Fix: run terraform validate, correct syntax, and scan rendered modules when using generated IaC.
Best Practices
Do
- Gate only on HIGH/CRITICAL initially to reduce rollout friction.
- Separate reporting from blocking by generating SARIF/JSON on every build and enforcing policy on protected branches.
- Scan both image and source because secrets and IaC issues may not appear in the final image.
- Baseline and tune using
.trivyignorefor accepted risk with ticket references.
Don't
- Don't fail builds on every unfixed CVE without triage; use
--ignore-unfixedwhere patch cadence is outside your control. - Don't allow direct internet DB downloads from every runner in regulated environments.
- Don't store scan outputs in public artifacts; they can reveal internal package versions and file paths.
A practical enterprise pattern is: local developer scans, mandatory PR scanning for source and IaC, image scanning before registry promotion, and nightly rescans of released artifacts for newly disclosed CVEs.
Have a project in mind?
Get an instant AI price estimate for it, or talk directly to our team.
One email a month on what we learn building with AI