A team runs `trivy convert --format cyclonedx` over last year's Trivy JSON reports to re-check old releases — why does that not answer the question?
answer
- re-rendering is not re-scanning
- the JSON is a snapshot
- no database lookup at all
- packages present only if they were listed
- a default that changed in 0.67.0
basics
~20 strivy convert re-renders an existing Trivy JSON report into another format without consulting the vulnerability database, so it repeats last year's findings. Re-checking needs trivy sbom on a stored SBOM, which matches the packages against today's advisories.
solid answer
~40 s`trivy convert` reads a Trivy JSON report and writes it as a table, SARIF, CycloneDX, SPDX and so on, applying filters such as `--severity` on the way. It does not scan and it does not open the vulnerability database, so a converted year-old report shows only the advisories that were known when the JSON was written. To re-check, you need an SBOM and `trivy sbom`. There is a second trap: the CycloneDX file is built from the report's package list, which exists only if the scan listed all packages. `--list-all-pkgs` has defaulted to true since 0.67.0, but a report written earlier with the old default has no package list, so its converted SBOM has no package components either. Reports from `trivy k8s` and AWS scans are not supported at all.
code
bash · 3 linestrivy image --format json --output app-1.4.0.json registry.example.internal/shop/app:1.4.0
trivy convert --format cyclonedx --output app-1.4.0.cdx.json app-1.4.0.json
trivy sbom app-1.4.0.cdx.jsongo deeper
Remember that trivy convert turns a Trivy JSON report into another format and does not scan anything.
Explain that convert applies filters but never opens the database, and that the SBOM it writes depends on the package list stored in the JSON.
Show you would check an archived report for a package list before trusting it, and use trivy sbom on stored SBOMs for any question about today's exposure.
Decide what a release must archive, SBOM, JSON or both, so that the organisation can answer both what was known then and what is known now.
## What `trivy convert` is for Trivy's JSON report is its richest output: every result, finding and, by default, every package. `trivy convert` takes that file and **re-renders** it in another format, so that a pipeline can scan once and publish several outputs: ```bash trivy image --format json --output result.json registry.example.internal/shop/app:1.4.0 trivy convert --format sarif --output result.sarif result.json trivy convert --format table --severity CRITICAL result.json ``` The **filter options** apply during conversion: `--severity`, the ignore file given by `--ignorefile`, and `--ignore-policy`. `--exit-code` is also accepted, so a conversion can fail a job on the findings it renders. ## What it does not do | Expectation | What Trivy 0.74.0 actually does | |---|---| | Fetch new advisories | Never: no database is opened, so findings are exactly as written | | Run extra scanners | No: `--scanners` on `convert` only tells the summary table which scanners were used | | Accept any JSON | Only Trivy reports; reports from Kubernetes and AWS scans are rejected | | Always yield a full SBOM | Only when the JSON carries a package list | So converting last year's report produces last year's answer in a new format. That is useful as **evidence of what was known then**, and useless as a re-check. ## The package-list trap 1. Trivy's JSON writer drops each result's `Packages` array when `--list-all-pkgs` is false. 2. `--list-all-pkgs` defaulted to false until **Trivy 0.67.0**, which changed the default to true. 3. A report written before then, without the flag, therefore lists only findings, not the inventory. 4. The CycloneDX and SPDX encoders build components from that package list, and attach vulnerabilities to those components. With no packages there are no package components, and so nothing to re-check later. Check before you rely on an archived report: ```bash jq '[.Results[]?.Packages // [] | length] | add' result.json ``` A result of zero or `null` means the report never held an inventory. ## Re-checking correctly - Keep an **SBOM per release**, written at release time with `--format cyclonedx` or `spdx-json`, or converted once from a JSON report that does carry packages. - Run **`trivy sbom`** on it whenever you want today's view. It rebuilds the package list and matches it against the current database. - To refresh the archived CycloneDX file itself, `trivy sbom --scanners vuln --format cyclonedx` writes the original BOM back with a new vulnerabilities section (0.67.0 and later). ## A worked example A platform team kept a Trivy JSON report for every release since early 2025. After a widely publicised advisory, someone proposes converting all of them to CycloneDX and calling the converted files the answer. 1. The conversions finish in seconds and the files look like SBOMs. 2. None of them mentions the new advisory, because each one holds only the findings from its original scan date. 3. The reports written before the team's Trivy upgrade past 0.67.0 produce CycloneDX files with no package components, because those reports never held a package list. The team splits the archive. Reports with a package list are converted once to CycloneDX and then re-checked with `trivy sbom`. Releases whose reports lack a package list can only be re-checked by scanning the image again, if it still exists. ## When convert is the right tool - **One scan, many formats** in CI: SARIF for code scanning, a table for the log, CycloneDX for the archive, all from one analysis. - **Faithful reproduction**: an auditor asks what the scanner reported when a release shipped. `convert` re-renders that answer without mixing in advisories published later. - **Re-filtering**: the JSON kept every severity, and a team now wants only the critical findings in a table. ## Summary `convert` changes the **shape** of a result; `trivy sbom` changes its **date**. Mixing the two up gives a team a reassuring, stale answer to the question of which past releases are exposed today.
- Can `trivy convert` add license findings that the original scan did not collect?No. It only re-renders what the JSON holds. `--scanners` on `convert` exists so the summary table knows which scanners ran; license findings must come from a scan run with `--scanners license`.
- When is replaying old findings exactly what you want?When the question is what the scanner said at the time, for example an audit of what was known when a release shipped. `convert` reproduces that report in another format without mixing in advisories published later.
saying these in an interview costs you the question
- trivy convert refreshes the vulnerabilities from the latest database.
- Any Trivy JSON report converts into a complete SBOM.
- Passing --scanners license to convert adds license findings to an old report.
- trivy convert accepts reports from trivy k8s.
- A converted old report and a fresh trivy sbom run always agree.