Skip to content

docker scout cves panics with SIGSEGV in vex.GenerateCanonicalID — org-scoped exception data deserializes to empty VEX document (nil Timestamp) #231

@jandroav

Description

@jandroav

Summary

Since 2026-06-09 ~05:30 UTC, every docker scout cves scan of liquibase/liquibase-secure images run in the context of our Docker organization crashes with a nil-pointer panic in internal/vex.GenerateCanonicalID (vex.go:179). The same scan in personal/anonymous context passes. It reproduces with no --vex-location at all and on every CLI version we tested (1.18.4, 1.19.0, 1.20.3, 1.20.4, 1.21.0), and began without any client-side change (same pinned CLI, runner image, base image digest, Dockerfile). Everything points to an exception/VEX document served by the Scout platform for our org that the CLI converts into an empty document and then dereferences.

Stack trace

✓ Loaded 42 VEX documents
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x111b0b1]

github.com/docker/scout-cli-plugin/internal/vex.GenerateCanonicalID({{{0x0, 0x0}, {0x0, 0x0}, {0x0, 0x0}, {0x0, 0x0}, 0x0, 0x0, ...}, ...})
	internal/vex/vex.go:179 +0x31
github.com/docker/scout-cli-plugin/internal/vex.ApplyVEX({...}, 0xc08dc5cb00, {0xc00083dce0, 0x2b, ...})
	internal/vex/vex.go:137 +0x1b8
github.com/docker/scout-cli-plugin/cves.(*Lister).FromSBOM(...)
	cves/cves.go:133 +0x708

Reproduction

Requires an account belonging to the affected organization (liquibase), with the org set as the Scout context — the bug does not reproduce in personal context:

docker login                                       # account in the liquibase org
docker scout config organization liquibase
docker pull liquibase/liquibase-secure:latest
docker scout cves liquibase/liquibase-secure:latest \
  --format sarif --output out.sarif --only-severity critical,high
# → panic; exit code 2; no SARIF written

Evidence

Scan (CLI v1.20.3 and v1.21.0) Result
liquibase-secure:latest, org context (org service account) PANIC
liquibase-secure:latest, personal context (no org set) PASS
same digest re-tagged to a neutral local name, org context PANIC
locally built image with same content, org context PANIC
liquibase-secure:5.1.1 (older content, pushed 2026-03-26), org context PASS
liquibase/liquibase:latest, alpine, eclipse-temurin, cassandra, neo4j, org context PASS
with/without --vex-location, any local VEX content irrelevant — panic persists with zero local VEX files

Additional data points:

  • The slice passed to ApplyVEX always contains exactly one more document than was loaded from disk (0 files → 1 doc; 42 files → 43 docs, the 0x2b in the trace). The extra document is entirely zero-valued: the panic argument decodes as a zero vex.VEX (go-vex layout — four empty strings, then Timestamp *time.Time = nil). GenerateCanonicalID starts with the equivalent of go-vex CanonicalHash() (doc.Timestamp.Unix()), which faults.
  • The extra document is appended in FromSBOM after LoadVEXs (the attestations.VexDocuments path). The image itself carries only standard buildx SPDX + SLSA provenance attestations; docker scout vex get reports "Found 0 VEX attestations".
  • Running with the org configured but an account without team permissions fails gracefully in the same code path with: could not list CVEs ... Path: [vulnerabilitiesByPackageForImageCoords] (query includes includeExcepted) — i.e., org-scoped exception data is fetched during cves, consistent with the crashing document being an org exception record.
  • Our Scout Dashboard shows no exceptions at all (Vulnerabilities → Exceptions: 0 entries, org-wide), so whatever record the backend serves to the CLI is not visible to us and we cannot remove it ourselves.
  • Scans passed until 2026-06-08 ~20:30 UTC and failed from 2026-06-09 ~05:30 UTC with no client-side change. liquibase/liquibase-secure is the only Scout-enrolled repo in our org.

Asks

  1. CLI hardening: nil-guard Timestamp (and skip/log empty documents) in GenerateCanonicalID/ApplyVEX instead of segfaulting — go-vex's own SortDocuments already nil-guards this field.
  2. Platform investigation: what exception/VEX record started being served for the liquibase org / liquibase/liquibase-secure around 2026-06-09 05:30 UTC, and why does it deserialize to an empty document in the CLI? (Also filed with Docker Support: ticket #____.)

Environment

  • scout CLI 1.18.4 / 1.19.0 / 1.20.3 / 1.20.4 / 1.21.0 — all panic (linux/amd64, GitHub Actions ubuntu-22.04; also reproduced via docker/scout-action v1.20.3)
  • Docker org: liquibase; affected repo: liquibase/liquibase-secure (Scout-enrolled)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions