diff --git a/tools/sbom-diff-and-risk/README.md b/tools/sbom-diff-and-risk/README.md index 6d96b3a..f296894 100644 --- a/tools/sbom-diff-and-risk/README.md +++ b/tools/sbom-diff-and-risk/README.md @@ -320,7 +320,7 @@ The [examples/](examples/) directory includes: - requirements-based sample reports at [sample-requirements-report.json](examples/sample-requirements-report.json) and [sample-requirements-report.md](examples/sample-requirements-report.md) After changing local example inputs, regenerate checked-in deterministic -examples with: +JSON, Markdown, summary, policy sidecar, and SARIF examples with: ```bash python scripts/regenerate-example-artifacts.py diff --git a/tools/sbom-diff-and-risk/docs/example-artifact-regeneration.md b/tools/sbom-diff-and-risk/docs/example-artifact-regeneration.md index 77c2c5a..a9cb0b1 100644 --- a/tools/sbom-diff-and-risk/docs/example-artifact-regeneration.md +++ b/tools/sbom-diff-and-risk/docs/example-artifact-regeneration.md @@ -28,6 +28,7 @@ The script regenerates these local, deterministic artifacts: - `examples/sample-policy-fail-report.md` - `examples/sample-requirements-report.json` - `examples/sample-requirements-report.md` +- `examples/sample-sarif.sarif` The strict-policy example intentionally exits with code `1` because it produces blocking local policy findings. The script treats that as expected while still @@ -47,11 +48,14 @@ policy-sidecar examples fail predictably. ## Boundaries -The regeneration script covers no-network JSON, Markdown, summary, and policy -sidecar examples produced through the public CLI. +The regeneration script covers no-network JSON, Markdown, summary, policy +sidecar, and strict-policy SARIF examples produced through the public CLI. It does not perform PyPI or Scorecard enrichment, does not call external services, and does not make dependency safety claims. Provenance-aware, -Scorecard-aware, and SARIF sample artifacts remain covered by their focused -golden tests because those examples include mocked evidence or normalized SARIF -metadata. +Scorecard-aware, and enriched SARIF sample artifacts remain covered by their +focused golden tests because those examples include mocked evidence. + +For `examples/sample-sarif.sarif`, the script normalizes the generated +`originalUriBaseIds.%SRCROOT%.uri` value to `file:///__PROJECT_ROOT__/` so +checked-in output does not depend on a maintainer's local checkout path. diff --git a/tools/sbom-diff-and-risk/docs/reviewer-evidence-pack.md b/tools/sbom-diff-and-risk/docs/reviewer-evidence-pack.md index df2c8fd..ab4aa30 100644 --- a/tools/sbom-diff-and-risk/docs/reviewer-evidence-pack.md +++ b/tools/sbom-diff-and-risk/docs/reviewer-evidence-pack.md @@ -56,8 +56,8 @@ No differences means the sample path reproduced the committed example output. `examples/sample-summary.json` is the summary-only artifact for the same run and is expected to match `examples/sample-report.json`'s `summary` object. -Maintainers can also verify checked-in no-network JSON, Markdown, summary, and -policy sidecar examples in one pass: +Maintainers can also verify checked-in no-network JSON, Markdown, summary, +policy sidecar, and SARIF examples in one pass: ```powershell python scripts/regenerate-example-artifacts.py --check diff --git a/tools/sbom-diff-and-risk/scripts/regenerate-example-artifacts.py b/tools/sbom-diff-and-risk/scripts/regenerate-example-artifacts.py index cd36338..8cd42ef 100644 --- a/tools/sbom-diff-and-risk/scripts/regenerate-example-artifacts.py +++ b/tools/sbom-diff-and-risk/scripts/regenerate-example-artifacts.py @@ -1,6 +1,7 @@ from __future__ import annotations import argparse +import json import os import subprocess import sys @@ -16,6 +17,7 @@ class ExampleArtifactSet: base_args: tuple[str, ...] outputs: tuple[tuple[str, str], ...] expected_exit_codes: tuple[int, ...] = (0,) + normalize_sarif_srcroot: bool = False ARTIFACT_SETS: tuple[ExampleArtifactSet, ...] = ( @@ -82,6 +84,22 @@ class ExampleArtifactSet: ("--out-md", "sample-requirements-report.md"), ), ), + ExampleArtifactSet( + name="strict-policy SARIF report", + base_args=( + "--before", + "examples/sarif_before.json", + "--after", + "examples/sarif_after.json", + "--policy", + "examples/policy-strict.yml", + ), + outputs=( + ("--out-sarif", "sample-sarif.sarif"), + ), + expected_exit_codes=(1,), + normalize_sarif_srcroot=True, + ), ) @@ -156,6 +174,14 @@ def _run_artifact_set(project_root: Path, output_root: Path, artifact_set: Examp f"{artifact_set.name} exited with {result.returncode}; " f"expected {artifact_set.expected_exit_codes}: {detail}" ) + if artifact_set.normalize_sarif_srcroot: + _normalize_sarif_srcroot(output_root / artifact_set.outputs[0][1]) + + +def _normalize_sarif_srcroot(path: Path) -> None: + payload = json.loads(path.read_text(encoding="utf-8")) + payload["runs"][0]["originalUriBaseIds"]["%SRCROOT%"]["uri"] = "file:///__PROJECT_ROOT__/" + path.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8") if __name__ == "__main__":