Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ For the SBOM tool's risk-model boundary, use
fields affect risk buckets, which fields are context only, and which claims the
model never infers.

For a short external case study, read
[SBOM Diff as a Bounded Policy Review Artifact](tools/sbom-diff-and-risk/docs/case-study-bounded-policy-review.md).

## Supporting Diagnostics Projects

These projects are internal supporting material for reviewer depth. They are
Expand Down
75 changes: 75 additions & 0 deletions tools/sbom-diff-and-risk/docs/case-study-bounded-policy-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# SBOM Diff as a Bounded Policy Review Artifact

An SBOM diff can answer a useful, limited question: what dependency evidence
changed between two inputs? It cannot decide whether a package is safe.

`sbom-diff-and-risk` keeps those statements separate. The tool produces a
deterministic component diff, local heuristic risk findings, and optional
policy decisions. Each layer remains visible in JSON, Markdown, SARIF, summary,
and policy-sidecar artifacts.

## Diff evidence comes first

The diff layer identifies added, removed, and changed components from
CycloneDX, SPDX, or supported dependency manifests. Component identity and
signature fields determine membership in those sets. They are not reputation
signals.

The local risk layer can attach bounded review buckets such as `new_package`,
`major_upgrade`, `version_change_unclassified`, `unknown_license`,
`suspicious_source`, and `not_evaluated`. The
[risk model boundary](../../../docs/risk-model-boundary.md) defines the exact
inputs for those buckets and the conclusions they do not support.

For example, `new_package` means a component appears only in the after input.
It does not mean the package is vulnerable or malicious. `not_evaluated`
preserves an unanswered question instead of filling an evidence gap with a
guess.

## Policy is a separate decision layer

A local policy can map diff or risk evidence to `pass`, `warn`, or `fail`.
Policy findings expose stable explanation fields:

- `decision_reason`
- `policy_rule`
- `severity_source`
- `matched_threshold`
- `observed_value`

Those fields let a reviewer see whether a decision came from a configured
threshold, a risk bucket, or a default policy severity. They do not upgrade the
decision into a dependency safety verdict. The full contract is documented in
[policy decision explainability](policy-decision-explainability.md) and the
[JSON report schema](report-schema.md).

## A small reproducible review surface

The checked-in examples include before/after inputs, generated reports, summary
JSON, policy sidecars, and bounded policy-decision fixtures for `pass`, `warn`,
`fail`, and consumer-side `needs-review`.

From `tools/sbom-diff-and-risk`, a reviewer can run:

```bash
python -m pip install -e .[dev]
python scripts/regenerate-example-artifacts.py --check
python scripts/regenerate-example-artifacts.py --check --only requirements
```

These checks use committed no-network examples. They verify that the examples
still match the code; they do not prove that a third-party dependency is safe.
The ordered evidence route is in the [reviewer path](reviewer-path.md).

## What remains a human decision

The tool can make a policy choice explicit, but it cannot decide whether that
policy fits a deployment context. Reviewers still need to ask whether a
threshold is appropriate, whether a missing license blocks release, whether a
source allowlist is justified, and whether an evidence gap should fail a gate
or remain `needs-review`.

The boundary is intentional: the artifact records what changed, which local
rule matched, and why the configured policy responded. It does not resolve
CVEs, inspect package contents for malware, infer exploitability, or certify a
package as safe.