trivy-image

Configures and runs Trivy for container image scanning: Aqua Security's all-in-one scanner combining vuln + secret + misconfiguration + license detection in one pass; trivy image {image} with --severity HIGH,CRITICAL filter; --format sarif/json (incl. scan-embedded CycloneDX; for standalone SBOM generation see syft-generation + sbom-formats); .trivyignore CVE suppression file; --ignore-unfixed for actionable filter; --scanners vuln/misconfig/license/secret toggle. Use when the team wants a single tool covering container image security across multiple dimensions, not for producing a standalone CycloneDX SBOM.

/plugin install qa-security-scanning@testland-qa

Overview

Per trivy.dev/latest/docs/target/container_image/ (opens in new window):

Trivy is Aqua Security's open-source scanner. Distinguishing feature: all-in-one - one CLI invocation covers vuln + secret + misconfig + license scanning. By contrast, syft-generation's Grype workflow is a two-step SBOM-then-scan pattern.

Per tv-img (opens in new window) the scanner toggles:

ScannerDefault?Use
vulnyesKnown CVEs in OS + language packages
secretyesExposed credentials (env vars, config files)
misconfignoDocker / Kubernetes config best-practices
licensenoLicense compliance scanning

When to use

  • Container-image security in one tool (vs separate tools per concern).
  • The team uses Aqua Security stack (Trivy is the OSS center of it).
  • Pre-prod or registry-side scanning (Trivy's image-by-tag mode).
  • Layered with the Grype workflow in syft-generation for cross-DB consensus on vuln findings.

Step 1 - Install

Common install paths:

# Homebrew (macOS / Linux)
brew install trivy

# Docker (zero-install for CI)
docker pull aquasec/trivy:latest

# Linux APT
sudo apt-get install trivy

# RPM
sudo dnf install trivy

Step 2 - Basic image scan

Per tv-img (opens in new window):

# Default: vuln + secret scan
trivy image python:3.4-alpine

Example with multiple toggles:

# All scanners (vuln + secret + misconfig + license)
trivy image --scanners vuln,secret,misconfig,license python:3.4-alpine

# Vuln-only (fastest, default if --scanners omitted defaults to vuln+secret)
trivy image --scanners vuln python:3.4-alpine

Step 3 - Severity filtering

Per tv-img (opens in new window):

trivy image --severity HIGH,CRITICAL python:3.4-alpine

Severity levels: UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL.

Combined with exit-code-on-finding:

trivy image --severity HIGH,CRITICAL --exit-code 1 python:3.4-alpine

Exit code semantics: 0 = no findings at the configured severity; 1 = findings present.

Step 4 - Output formats

Per tv-img (opens in new window):

FormatUse
jsonFor multi-scanner finding prioritization
sarifGitHub Code Scanning upload
cyclonedxCycloneDX SBOM with vuln annotations
spdx-jsonSPDX SBOM (vuln-only metadata)
templateCustom Go template
(default)Table format human-readable
trivy image --format json --output trivy-image.json my-image:1.0
trivy image --format sarif --output trivy-image.sarif my-image:1.0
trivy image --format cyclonedx --output trivy-cyclonedx.json my-image:1.0

Step 5 - --ignore-unfixed for actionable filter

Per tv-img (opens in new window), --ignore-unfixed excludes vulnerabilities without an available fix - the practical first-line filter for actionable findings:

trivy image --ignore-unfixed python:3.4-alpine

Combine with a severity threshold for the recommended PR-blocking config (fail only on actionable, high-severity vulns):

trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 my-image:1.0

Step 6 - Secret scanning

Per tv-img (opens in new window):

"Secret detection runs automatically. The tool scans for exposed credentials and sensitive data, particularly in environment variables."

Secret findings appear alongside vuln findings in the same report. For deeper secret-scanning patterns, see gitleaks-scanning

  • trufflehog-scanning.

Step 7 - Misconfiguration scanning

Per tv-img (opens in new window):

trivy image --scanners misconfig --severity HIGH,CRITICAL my-image:1.0

Detects Docker / Kubernetes config patterns matching CIS Benchmarks

  • team-policy issues (e.g., container running as root, missing HEALTHCHECK, exposed sensitive ports).

For comprehensive IaC scanning (not just image-internal config), use checkov-policy

  • trivy-config from the qa-iac plugin.

Step 8 - False-positive triage (MANDATORY)

Per tv-img (opens in new window): "Use a .trivyignore file to suppress specific findings. Place this file in your project directory with CVE IDs or vulnerability identifiers you wish to exclude."

Suppression mechanisms:

MechanismUse
.trivyignore filePer-CVE / per-misconfig-rule ID list
--ignore-unfixed flagFilter to actionable findings only
--vex (VEX file)Standardized status assertions (CycloneDX-VEX or OpenVEX)
--ignore-policy Rego policyProgrammatic ignore via OPA Rego

.trivyignore example:

# .trivyignore
# Reason: log4j-core 2.14.x bundled but not loaded at runtime
#         (verified via dependency tree analysis)
# Approved-by: alice@example.com
# Re-review-date: 2026-09-15
CVE-2021-44228
CVE-2021-45046

# Misconfiguration ignores
DS013
KSV001

Justification template (mandatory): every entry in .trivyignore should be preceded by # Reason: ... # Approved-by: ... # Re-review-date: ... comment block.

For richer programmatic suppression, use OpenVEX:

trivy image --vex sbom.openvex.json --severity HIGH,CRITICAL my-image:1.0

The VEX file's per-CVE assertions (not_affected etc.) filter the output.

Cadence: every quarter, audit .trivyignore; expired re-review-date entries removed.

Step 9 - CI integration

Wrap the CLI with the aquasecurity/trivy-action GHA to scan the built image and upload SARIF to GitHub Code Scanning. The full GitHub Actions workflow is in references/ci-and-composition.md.

Step 10 - Composition with sister tools

Trivy is the all-in-one first line; compose it with syft-generation for a standalone SBOM plus the Grype scan for cross-DB consensus on findings, and checkov-policy for deeper IaC scanning. The full composition table is in references/ci-and-composition.md.

Anti-patterns

Anti-patternWhy it failsFix
Skip --ignore-unfixedStuck findings (no fix available) flood reportAlways for PR gating (Step 5)
.trivyignore without justification commentNo audit trailMandatory template (Step 8)
Run all scanners on every PRSlow; misconfig + license noise on small changesDefault vuln+secret on PR; full scan nightly
Skip severity filterLOW noise drowns CRITICAL signal--severity CRITICAL,HIGH for PR (Step 3)
Pin to aquasec/trivy:latest Docker tagBreaking changes mid-releasePin specific version

Limitations

  • DB updates are large (~1 GB cache); pin DB version for CI determinism.
  • Misconfig + license + secret scanning are less deep than dedicated tools (use Trivy as first-line; layer dedicated tools for depth).
  • Trivy's vuln DB has its own coverage profile; pair with Grype (syft-generation Step 7) for cross-DB consensus.
  • License detection is basic; for compliance-grade analysis, use ScanCode / FOSSology.

References

  • tv-img (opens in new window) - container image scan reference
  • trivy.dev - landing
  • aquasecurity.github.io/trivy - full documentation
  • github.com/aquasecurity/trivy - repository
  • openvex.dev - OpenVEX specification (used by --vex flag)
  • references/ci-and-composition.md - full CI workflow + sister-tool composition
  • syft-generation, sbom-formats - sister tools
Reference

trivy-image CI integration and tool composition

View source (opens in a new tab)

Extracted from trivy-image. The SKILL.md spine keeps the scan commands inline; the full CI workflow and the sister-tool composition table live here.

CI integration

jobs:
  trivy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - run: docker build -t my-app:${{ github.sha }} .
      - uses: aquasecurity/trivy-action@master
        with:
          image-ref: my-app:${{ github.sha }}
          format: sarif
          output: trivy.sarif
          severity: CRITICAL,HIGH
          ignore-unfixed: true
          exit-code: 1
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with: { sarif_file: trivy.sarif }

The aquasecurity/trivy-action GHA wraps the CLI plus SARIF upload.

Composition with sister tools

Sister toolUse
syft-generationGenerates standalone SBOM (Trivy embeds SBOM gen but exposes it less)
Grype (syft-generation Step 7)Alternative scanner; cross-DB consensus on findings
sbom-formatsReference for the SBOM formats Trivy outputs
checkov-policyCross-plugin: deeper IaC scanning vs Trivy's image-internal misconfig