Teams need one scanner they can run on a laptop, in every pipeline and against a live cluster to find vulnerable packages, misconfigured infrastructure code, leaked secrets and licence problems before they ship. Trivy, an Apache 2.0 open source project from Aqua Security, is widely used for that job. This guide explains what Trivy scans, the commands and flags that matter in practice, how to run it safely in CI/CD and offline environments, how to manage its vulnerability databases, and what the March 2026 compromise of Trivy's own release channels teaches about running any security tool in a pipeline. It is written for application security engineers, platform and DevOps teams and vulnerability managers. It describes defensive use only, based on the project's official documentation.
Key takeaways
- Targets plus scanners. Trivy scans container images, filesystems, remote git repositories, VM images, Kubernetes clusters and SBOMs, using scanners for vulnerabilities, misconfigurations, secrets and licences.
- Exit code 0 by default. Trivy reports findings but does not fail a build until you set
--exit-code 1, usually with a--severitythreshold. - The database is a dependency. Vulnerability, Java and checks databases are pulled as OCI artefacts at scan time; cache or mirror them for reliability and air-gapped use.
- Pin and verify the scanner itself. In March 2026 attackers force-pushed trivy-action tags and published a malicious release; pin actions to commit SHAs and images by digest, and verify Cosign signatures.
- Suppressions need governance.
.trivyignoreand VEX files are powerful; require owners, reasons and expiry dates for every entry.
What the tool does
Trivy is a single Go binary, also shipped as the aquasec/trivy container image and through package managers such as Homebrew, apt and yum. The general form is trivy <target> [--scanners <list>] <subject>. Ecosystem integrations include the trivy-action GitHub Action, the Trivy Operator for Kubernetes and a VS Code extension. Canary builds are produced from every push to main and the project states they are not for production.
| Target (subcommand) | What it scans | Main scanners | Typical use |
|---|---|---|---|
trivy image | Container image layers: OS packages and language dependencies | vuln, secret | Build gate and registry rescans |
trivy fs / trivy rootfs | Local project directory or an unpacked root filesystem | vuln, secret | Developer pre-commit checks, scanning a build context |
trivy repo | Remote git repository | vuln, secret | Periodic scans of repositories outside your pipelines |
trivy config | IaC files: Terraform, CloudFormation, ARM, Kubernetes manifests, Helm, Dockerfile, Ansible | misconfig | Pull request checks on infrastructure code |
trivy k8s | Cluster resources, workload images, node components (experimental) | vuln, misconfig, secret | Posture snapshots of running clusters |
trivy vm | Virtual machine images | vuln, secret | Golden image checks |
trivy sbom | An existing CycloneDX or SPDX SBOM | vuln | Rescanning shipped software as new CVEs appear |
The scanner column is a guide: the documentation states that secret scanning is on by default and misconfiguration scanning is enabled explicitly with --scanners misconfig outside trivy config; check trivy <target> --help for your version. Licence scanning is always opt-in with --scanners license.
Defender use cases
Vulnerability scanning
For OS packages installed by dpkg, yum or apk, Trivy uses the OS vendor's own advisories, because vendors backport fixes and their fixed versions differ from upstream. For language packages installed by pip, npm and similar, it uses the GitHub and GitLab advisory databases. Severity also comes from the selected vendor source in preference to NVD, so a CVE rated HIGH in NVD can appear as LOW for a Red Hat package. Useful flags:
--severity HIGH,CRITICAL: limit output and gating to what you will act on.--ignore-unfixed: hide findings with no fix (shorthand for ignoring the affected, will_not_fix, fix_deferred and end_of_life statuses). Good for build gates, poor for risk reporting.--exit-on-eol: fail when the base OS is end of life, which otherwise can show zero findings because no fixes are published.--dependency-tree: show which direct dependency pulled in a vulnerable package (table format).
Prioritise by exploitability, not count. See the Vulnerability Prioritisation Guide and Container Image Security Guide.
Misconfiguration and IaC scanning
trivy config --severity HIGH,CRITICAL ./iac evaluates built-in checks from the trivy-checks bundle. You can add organisation policies as Rego custom checks (for example required tags on AWS resources) with --config-check and a namespace. The checks bundle is embedded in the binary as a fallback, so misconfiguration scanning still works offline using the checks from the release date. See the Infrastructure as Code Security Guide.
Secret scanning
Secret scanning reads every plaintext file and compiled Python (.pyc) files, with built-in rules for AWS access keys, GCP service accounts, GitHub and GitLab personal access tokens, Slack tokens and many more. Built-in allow rules skip common test paths; custom rules, allow rules and enable or disable rules go in a YAML file passed with --secret-config. Scanning image layers matters because a secret removed in a later layer still exists in an earlier one. Every hit is a machine credential: revoke and rotate it, do not just delete the file. See the Git Secret Scanning Guide and Secrets Management Guide.
SBOM generation and scanning
trivy image --format cyclonedx --output sbom.json <image> or --format spdx-json produces an SBOM. Note that --format cyclonedx disables vulnerability scanning unless you add --scanners vuln. Store the SBOM with the artefact and rescan it with trivy sbom when new CVEs are published, which avoids pulling the image again. VEX documents (--vex) can suppress findings a supplier has declared not exploitable; VEX support is marked experimental. See the SBOM Guide.
Licence scanning
--scanners license classifies package licences by risk category; --license-full extends detection to licence text in files, with a classifier confidence level adjustable from 0.0 to 1.0 (default 0.9). Use --ignored-licenses for licences your policy accepts. Treat results as input to legal review, see the Open Source Licence Compliance Guide.
Kubernetes
trivy k8s --report summary scans the cluster in the current kubeconfig context; --report all gives detail. It needs read roles across the resources it inspects and runs a node-collector job for node checks unless --disable-node-collector is set. Scope with --include-namespaces or --exclude-kinds, and run it with a dedicated read-only identity rather than a cluster admin kubeconfig. See the Kubernetes Security Guide.
Deployment and safe use
Phased rollout in CI/CD
- Observe: run Trivy on main branch builds with
--exit-code 0, output JSON or SARIF (--format sarif, SARIF 2.1.0) to your code scanning or vulnerability platform, and measure the baseline. - Gate new risk: fail pull requests with
--exit-code 1 --severity CRITICALfor fixable findings and HIGH or CRITICAL misconfigurations and secrets, leaving existing debt to the backlog. - Tighten: add HIGH,
--exit-on-eoland licence policy once false positive handling is stable. - Extend: schedule rescans of registries and stored SBOMs, and periodic
trivy k8sposture runs. - Roll back: if a gate blocks delivery wrongly, drop to observe mode for that rule and record a time-limited suppression, rather than removing the scan step.
Securing the scanner itself
A scanner runs where secrets live: CI runners with cloud credentials, registry tokens and signing keys. The Trivy supply chain attack showed the risk. After a pull_request_target workflow exposed a privileged token in February 2026 and credential rotation proved incomplete, attackers on 19 March 2026 published malicious Trivy v0.69.4 and force-pushed most trivy-action tags and all setup-trivy tags, followed by malicious Docker Hub images 0.69.5 and 0.69.6. Pipelines that referenced those tags ran a stealer that read secrets from the runner's memory and searched for SSH keys, cloud credentials and Kubernetes tokens (CVE-2026-33634, advisory GHSA-69fq-xp46-6x23). Credentials stolen this way were then used in the Checkmarx KICS supply chain attack. Controls that follow:
- Pin actions to full commit SHAs:
uses: aquasecurity/trivy-action@<40-character SHA>with the version in a comment; tags can be moved, SHAs cannot. Let a dependency bot propose updates with a cooldown before adoption. - Pin images by digest:
aquasec/trivy@sha256:..., neverlatest; never use canary builds in pipelines. - Verify signatures: binaries and images are signed with Cosign. Verify images keylessly with
cosign verify, the certificate identity matching Trivy's GitHub workflows and the issuerhttps://token.actions.githubusercontent.com; since v0.68.1 release assets carry.sigstore.jsonbundles forcosign verify-blob. RPM and Deb packages are also GPG signed. - Least privilege for the scan job: run scanning in a job with a read-only
GITHUB_TOKENand no deployment or cloud secrets in its environment. - Trusted templates only: the docs warn that custom report templates can read environment variables and put sensitive values in output.
See the GitHub and GitHub Actions Security Guide and CI/CD Security Guide.
Databases, caching and offline use
| Database | Artefact | Used for | Key flags |
|---|---|---|---|
| Vulnerability DB | trivy-db | CVE data from vendor and ecosystem feeds | --db-repository, --skip-db-update, --download-db-only |
| Java DB | trivy-java-db | Identifying JAR artefacts by digest | --java-db-repository, --skip-java-db-update |
| Checks bundle | trivy-checks | Misconfiguration check logic | --checks-bundle-repository, --skip-check-update |
By default Trivy pulls databases from mirror.gcr.io/aquasec then ghcr.io/aquasecurity, and the project notes public infrastructure can rate limit under load. For many runners or restricted networks, mirror the OCI artefacts into an internal registry, point --db-repository at it (keep the official locations in the list if you want fallback), and refresh it on a schedule. trivy-action caches databases in $GITHUB_WORKSPACE/.cache/trivy by default. In air-gapped environments add --offline-scan to stop Maven Central lookups. Track database age: a scan against a week-old database misses a week of CVEs. trivy clean --vuln-db removes a corrupted cache.
Data handling and licensing
Trivy is licensed under Apache 2.0, so internal use, modification and redistribution are permitted under its terms. It collects anonymous usage telemetry (a hashed installation identifier, version, OS and non-revealing flags) and checks for updates at check.trivy.dev; disable both with --disable-telemetry and --skip-version-check, since either flag alone still allows connections. Reports contain package inventories and secret findings with file paths and partial matches, so store them with access control.
Detection and hardening value
| Risk | Trivy capability | Framework mapping |
|---|---|---|
| Known vulnerable packages shipped | image, fs, sbom vulnerability scans with gating | NIST SP 800-53 RA-5, SA-11; CSF 2.0 ID.RA-01 |
| Unknown software inventory | CycloneDX and SPDX SBOM generation | CM-8, SR-4; CSF 2.0 ID.AM-02 |
| Insecure infrastructure defaults | trivy config, custom Rego checks | CM-6; CSF 2.0 PR.PS-01 support |
| Credentials in images and repositories | Secret scanner | ATT&CK T1552.001 Credentials In Files |
| Tampered or backdoored base images | Image scanning plus Cosign verification of images you consume | ATT&CK T1525 Implant Internal Image; SR-11 |
| Compromised dependencies and tools | Vulnerability and SBOM scanning (detects known, not novel, malicious packages) | ATT&CK T1195.001, T1195.002; SA-15 |
| Unmaintained software | --exit-on-eol | CSF 2.0 PR.PS-02 |
Metrics
- Coverage: percentage of production images and IaC repositories scanned in the last 7 days.
- Mean time to remediate fixable CRITICAL findings in deployed images, against your SLA.
- Database freshness: age of the vulnerability database at scan time (target under 24 hours).
- Suppression hygiene: share of
.trivyignoreor VEX entries with an owner and expiry date (target 100%). - Secrets found and rotated: time from secret detection to revocation.
- Pinning: percentage of workflows referencing scanner actions by SHA and images by digest.
Alternatives
| Option | Scope | When it fits |
|---|---|---|
| Trivy | Vulnerabilities, IaC, secrets, licences, SBOM, Kubernetes in one binary | One tool for many targets with a single output pipeline |
| Grype and Syft (Anchore, Apache 2.0) | Syft generates SBOMs (CycloneDX, SPDX, Syft JSON); Grype scans images, filesystems and SBOMs for vulnerabilities, with EPSS and KEV prioritisation | Teams that want SBOM generation and vulnerability matching as separate steps, or a second opinion on findings |
| Dedicated IaC and secret scanners | Deeper rule sets for one domain | Large IaC estates or a central secret scanning programme across all repositories and history |
| Commercial container and SCA platforms | Runtime context, reachability, policy and reporting at scale | Large organisations needing central dashboards and support |
Small teams usually get most value from Trivy in CI plus scheduled registry rescans. Larger organisations often run two scanners for comparison and feed both into a vulnerability management platform. See the Container Security Guide and Container Security Buyer's Guide.
Common failure patterns
- Scan without gate: forgetting
--exit-codemeans every build passes regardless of findings. - Floating tags for the scanner:
@master,@v0or:latestreferences pulled the stealer in March 2026; pin by SHA and digest. - Permanent suppressions: ignore files without expiry dates quietly accumulate accepted risk.
- Stale or rate-limited databases:
--skip-db-updateleft in place or failed downloads produce clean-looking reports. - Deleting found secrets instead of rotating them: the credential remains valid in image layers, caches and git history.
- Treating zero findings as safe: end-of-life images and
--ignore-unfixedboth hide risk.
Practitioner checklist
- Pin trivy-action and setup-trivy to full commit SHAs and the Trivy image by digest; never use canary builds.
- Verify Cosign signatures on Trivy binaries and images before adding a new version to the approved toolset.
- Run scan jobs with a read-only token and no deployment or cloud secrets in scope.
- Start in observe mode, then gate on fixable CRITICAL findings with
--exit-code 1and widen gradually. - Enable
--scanners vuln,misconfig,secreton repositories andtrivy configon IaC pull requests. - Generate CycloneDX or SPDX SBOMs for every release and rescan them on a schedule.
- Mirror trivy-db, trivy-java-db and trivy-checks internally and alert when the database is older than 24 hours.
- Require owner, reason and expiry for every
.trivyignoreand VEX entry. - Rotate every secret Trivy finds and record time to revocation.
- Decide on telemetry and version checks and set
--disable-telemetryand--skip-version-checkwhere policy requires.
Standards and references
- Aqua Security: Trivy repository and documentation
- Aqua Security: Trivy signature verification
- Aqua Security: trivy-action GitHub Action
- Aqua Security: Trivy databases
- NIST: SP 800-53 Rev. 5
- NIST: Cybersecurity Framework 2.0
- MITRE ATT&CK: Compromise Software Supply Chain
- Anchore: Grype repository
Related NHI Mgmt Group resources: Container Security Guide · SBOM Guide · Infrastructure as Code Security Guide · Git Secret Scanning Guide · Software Supply Chain Security Guide