Aqua Security's Trivy reached v0.69.1 on October 28, 2025, the latest in a year-long cadence that started with v0.59.0 on January 30, 2025 and shipped roughly one minor release per month. v0.69 is not a flashy release the way v0.60 was — it consolidates VEX handling, adds two new identifier fields, and quietly fixes the misconfig cataloger that had been a memory hog since the Helm support landed. We ran v0.69 against the same 1.2 GB internal python:3.12-slim derivative we benchmarked v0.59 on in February, and the upshot is real but undramatic: faster on most images, more useful in pipelines, and noticeably better at suppressing known-non-exploitable noise.
What changed between v0.59 and v0.69?
The headline items, pulled from the upstream CHANGELOG.md, are: (1) VEX support promoted from experimental — --vex now accepts directories of OpenVEX, CSAF, and CycloneDX VEX documents and applies them by default when present in ~/.trivy/vex/; (2) ArtifactID and ReportID fields added to JSON reports so downstream consumers can correlate the same image scan across multiple runs without hashing the full result; (3) the Java SBOM cataloger now resolves Gradle composite builds correctly; (4) the misconfig scanner moved its Rego evaluator off the deprecated OPA v0 API and onto the v1.x API; (5) image scanning of docker-archive:// tarballs is roughly 18% faster because the cataloger no longer extracts overlays twice. Most teams will not notice (4) or (5) directly, but if you parse --format json output for compliance, (2) is the most material change in the year.
How does the new VEX-by-default behaviour work?
VEX in Trivy used to require --vex path/to/file.json per invocation. Starting in v0.65 and finalised in v0.69, Trivy looks in $XDG_CONFIG_HOME/trivy/vex/ (typically ~/.trivy/vex/) for any document and automatically applies statements matching the current image's purls. The matching logic accepts both exact-version and version-range statements, and emits a structured suppression record in the JSON output:
{
"VulnerabilityID": "CVE-2024-12345",
"Status": "not_affected",
"Justification": "vulnerable_code_not_present",
"Source": "openvex://acme-internal/2025-q3.json"
}
We tested this against an internal VEX directory of 142 statements covering known-non-exploitable findings in our base images. With the directory populated, the scan reported 38 fewer "Critical" findings than v0.59 — every one of which corresponded to a deliberate suppression. The auditable trail is the part procurement teams ask for, and v0.69 finally produces it without bespoke scripting.
Did the speed claims hold up?
Mostly. The release notes claim "up to 18% faster" docker-archive scans; we measured 14.6% on a 1.2 GB image (23.4s median over 10 runs in v0.59 → 20.0s in v0.69 on the same M2 Mac mini, vulnerability DB pre-warmed). Filesystem scans of a Go monorepo were flat (within 2%). Misconfig scans of a 600-Terraform-file repo improved more dramatically — 94s to 71s, a 24% win — because the Rego v1 API path avoids re-parsing modules per resource. If you run misconfig scanning in PR checks the wallclock difference is meaningful.
| Scan target | v0.59.0 | v0.69.1 | Delta | | --- | --- | --- | --- | | 1.2 GB python image (filesystem cache cold) | 31.2s | 27.8s | -10.9% | | 1.2 GB python image (cache warm) | 23.4s | 20.0s | -14.6% | | Go monorepo SCA (filesystem) | 11.8s | 11.5s | -2.5% | | 600-file Terraform misconfig scan | 94s | 71s | -24.5% | | SBOM generation (CycloneDX 1.6) | 18.1s | 17.4s | -3.9% |
What about the supply chain incidents around Trivy in early 2026?
This is the part you cannot ignore if you are evaluating the project today. In February 2026, two separate compromise events affected the Trivy publishing pipeline within two weeks, surfacing first as anomalous binary signatures on the aquasecurity/trivy Homebrew tap and then as a tampered trivy-db artifact published to the GHCR registry. The maintainers responded quickly, rotated keys, and published a post-mortem. The practical implication for teams running v0.69 in CI is to pin to a specific SHA, verify the Cosign signature against the upstream public key, and avoid the floating :latest tag for both the binary and the vuln-DB OCI artifact. The trivy --skip-db-update flag combined with a self-hosted DB mirror via oras is the most resilient pattern we have seen in production.
How should existing users plan the upgrade?
Three concrete steps. First, regenerate any cached vulnerability DBs because v0.69 uses Bolt v1.3.10 with a slightly different schema — old caches still load but emit a deprecation warning. Second, audit any custom scripts that key off the JSON report by hashing the full body; the new ReportID field makes those hashes change even when findings do not, so switch to ReportID for idempotency checks. Third, if you have a homegrown VEX integration, move VEX documents into ~/.trivy/vex/ and drop the per-invocation --vex flag. We migrated three pipelines in roughly two hours; the longest part was reconciling our internal VEX directory layout, not the Trivy change itself.
# Recommended v0.69 pipeline invocation
trivy image \
--severity HIGH,CRITICAL \
--ignore-unfixed \
--vex-dir /etc/trivy/vex \
--format cyclonedx \
--output sbom.json \
--skip-db-update \
--db-repository registry.internal/trivy-db:2 \
registry.internal/myapp:${GIT_SHA}
How Safeguard Helps
Safeguard ingests Trivy v0.69 CycloneDX SBOMs and JSON vulnerability reports directly, mapping ArtifactID and ReportID to its internal asset graph so the same image scanned in CI, in the registry, and at runtime collapses into one finding rather than three. Griffin AI cross-references Trivy results against a separate scanner (Grype or OSV-Scanner) and surfaces disagreement — useful for catching the kind of catalog gaps that periodically show up in any one tool. Policy gates can require both a fresh Trivy scan and a matching VEX justification before promotion, and the multi-tool aggregator view lets security teams report on coverage across the whole estate without chasing per-team Trivy versions. For organisations running Trivy in CI today, Safeguard sits one layer up: it is the SBOM source of truth and the prioritisation engine, not a replacement for the scanner.