Trivy Advanced — Custom Policies, Air-Gapped Environments & VEX
Custom Misconfiguration Policies with Rego
Apply it against a manifest directory:
Trivy's built-in misconfiguration checks cover a broad set of common, well-known bad patterns out of the box — but an organization's OWN specific policies (a required label convention, a mandated resource-limit policy, an internal naming standard) go beyond what a generic tool ships with. Trivy supports custom policies written in Rego (the same policy language Open Policy Agent uses), letting an organization extend Trivy's checks with genuinely organization-specific rules rather than being limited to only the built-in defaults.
Air-Gapped / Offline Environments
For highly-regulated or genuinely air-gapped environments where scanning infrastructure can't reach the internet directly, Trivy supports a disconnected workflow — downloading the vulnerability database once on a connected machine, distributing it through an approved internal process, and running scans against that local copy. This requires an explicit, deliberate process for keeping the offline database current, since it won't auto-update the way a connected deployment would.
VEX (Vulnerability Exploitability eXchange)
Use it during a scan:
VEX is a structured, machine-readable format for expressing "this vulnerability exists in a component we ship, but our specific usage isn't actually exploitable" — a formalized, auditable alternative to an informal .trivyignore entry. This matters especially at scale/for compliance: a bare .trivyignore suppression is a local, tool-specific decision; a VEX statement is a portable, standardized claim that can be shared with downstream consumers of an image or SBOM, letting them make their own informed risk decisions rather than just seeing a suppressed finding with no context.
Trivy in a Multi-Stage CI/CD Pipeline
A mature pipeline separates build-time gating (blocking a bad deploy before it happens) from ongoing cluster scanning (catching newly-discovered vulnerabilities in already-deployed workloads) — these address genuinely different risk windows, and conflating them (only ever scanning at build time, never re-checking what's already running) leaves a real gap.
Comparing Findings Across Scans (Trend Tracking)
Beyond a single pass/fail gate, archiving structured JSON output over time enables trend analysis — is the count of accepted-but-unfixed findings growing or shrinking over successive builds? Is a specific dependency repeatedly the source of new findings, suggesting it should be replaced rather than continuously patched? This kind of longitudinal view requires deliberately archiving and comparing scan output, not something a single scan invocation provides on its own.
Performance Considerations at Scale
At real CI/CD scale (many pipeline runs per day across many repositories), a shared, persistent cache directory for the vulnerability database avoids every single run redownloading the entire database from scratch — a meaningful performance and reliability improvement, especially in ephemeral CI runner environments that would otherwise start from a completely cold cache every single time.
Try It (2 Minutes)
Using the VEX section above:
.trivyignore entry and a VEX statement, beyond just file format?You should land on: .trivyignore is a local, tool-specific suppression with no standard structure for sharing WHY across tools/organizations; VEX is a portable, standardized format expressing exploitability status that can be shared with downstream consumers, carrying structured justification; an outdated offline database means scans would miss any vulnerability discovered/added to the database after that snapshot, silently growing more inaccurate over time without an explicit process to refresh it; build-time scanning only catches what's known at build time — a vulnerability discovered in an already-deployed image's dependencies later requires re-scanning what's actually running to catch, which build-time-only gating structurally cannot do.

