Skip to content

Commit de50050

Browse files
fix(release): parse Grype 0.110 nested db.status identity
Grype >= 0.110 nests the vulnerability database identity under descriptor.db.status (built / schemaVersion / checksum inside the from URL); release_evidence.py still read the pre-0.110 flat db layout and failed the v1.6 release run with "container vulnerability database identity is incomplete" after every other gate had passed. Accept both shapes: when db.status is a mapping, merge its fields over the flat ones before validating. Adds a regression test using the exact structure emitted by scan-action/Grype 0.110.0 in run 32860273692. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
1 parent de0a363 commit de50050

2 files changed

Lines changed: 35 additions & 0 deletions

File tree

scripts/release_evidence.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,11 @@ def container_scan_artifact(root: Path, path: Path) -> dict[str, Any]:
718718
database = descriptor.get("db")
719719
if not isinstance(database, dict):
720720
raise EvidenceError("container vulnerability report must identify its database")
721+
# Grype >= 0.110 nests the database identity under db.status; older releases
722+
# wrote built/schemaVersion/checksum|from directly on db. Accept both shapes.
723+
status = database.get("status")
724+
if isinstance(status, dict):
725+
database = {**database, **status}
721726
built = database.get("built")
722727
schema_version = database.get("schemaVersion")
723728
checksum = database.get("checksum")

tests/test_release_evidence.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,36 @@ def test_release_evidence_accepts_identified_current_grype_database_shape(tmp_pa
11131113
}
11141114

11151115

1116+
def test_release_evidence_accepts_grype_0110_nested_db_status_shape(tmp_path):
1117+
root = _root(tmp_path)
1118+
dist = _dist(root)
1119+
inputs = _release_inputs(root, dist)
1120+
report = json.loads(inputs["image_scan"].read_text(encoding="utf-8"))
1121+
report["descriptor"]["db"] = {
1122+
"status": {
1123+
"schemaVersion": "v6.1.9",
1124+
"from": (
1125+
"https://grype.anchore.io/databases/v6/vulnerability-db_v6.1.9_"
1126+
"2026-08-25T00:17:00Z_1787638635.tar.zst"
1127+
"?checksum=sha256%3A" + "f" * 64
1128+
),
1129+
"built": "2026-08-25T06:17:15Z",
1130+
"path": "/home/runner/.cache/grype/db/6/vulnerability.db",
1131+
"valid": True,
1132+
},
1133+
"providers": {"ubuntu": {"captured": "2026-08-25T00:19:07Z"}},
1134+
}
1135+
inputs["image_scan"].write_text(json.dumps(report), encoding="utf-8")
1136+
1137+
evidence = _build(root, dist, inputs=inputs)
1138+
1139+
assert evidence["container"]["vulnerability_scan"]["database"] == {
1140+
"built": "2026-08-25T06:17:15Z",
1141+
"schema_version": "v6.1.9",
1142+
"checksum": "sha256:" + "f" * 64,
1143+
}
1144+
1145+
11161146
def test_repair_run_candidates_are_newest_first_and_bound_to_tag_commit_event():
11171147
runs = [
11181148
{

0 commit comments

Comments
 (0)