Share a Trivy scan report

A container scan produces two things: a list of CVEs, and a set of decisions about them. CI stores the first and loses the second. The finding scrolls past in a build log, someone decides it's not reachable from the entrypoint, and that decision lives in a Slack thread that is unfindable by the time the same CVE shows up next month.

Trivy already writes a readable artifact — the bundled HTML template produces one self-contained file. Give it a URL and the decisions have somewhere to live.

Publish it

trivy image --format template \
  --template "@contrib/html.tpl" \
  -o trivy.html \
  "$IMAGE" || true

curl -fsS -X PATCH \
  "https://commareports.com/api/v1/reports/$COMMA_REPORT_ID" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html trivy.html \
        --arg title "Trivy — $IMAGE — $(date +%F)" \
        '{title: $title, html: $html}')"

|| true because --exit-code 1 on HIGH findings is the run you most want published. PATCH on a saved report id keeps one URL per scan target with a revision per scan, which is what turns a pile of results into a trend.

Use a scoped token with reports:write only. Keep reports private or team-visible — see the sharing model. A vulnerability report is an inventory of what isn't patched yet, and it is private by default here for that reason.

What the URL changes

  • Triage notes stick to findings. Highlight the CVE row, pin the reasoning, and it's still attached on next month's scan. See commenting on HTML.
  • Scan-over-scan diffs. Which CVEs are new, which the base-image bump cleared. See revisions and diffs.
  • Auditors can read it. Someone with no CI access opens a link.
  • Scheduled rescans. A routine can refresh the report on a cron, so drift shows up without a push to trigger it — a base image gets a new CVE while your code sits still.

Limits

  • HTML body: 5 MB. A wide scan of a fat image can approach it; scan with --severity HIGH,CRITICAL for the published summary and attach the full JSON as an asset.
  • Scripts run, sandboxed: allow-scripts, no allow-same-origin.
  • 60 requests/minute per token.

Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision history.

Create your first report →

Related