Skip to content

Commit 531aa91

Browse files
committed
docs(sbom): add bounded policy review case study
1 parent 61af62b commit 531aa91

2 files changed

Lines changed: 78 additions & 0 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ For the SBOM tool's risk-model boundary, use
4141
fields affect risk buckets, which fields are context only, and which claims the
4242
model never infers.
4343

44+
For a short external case study, read
45+
[SBOM Diff as a Bounded Policy Review Artifact](tools/sbom-diff-and-risk/docs/case-study-bounded-policy-review.md).
46+
4447
## Supporting Diagnostics Projects
4548

4649
These projects are internal supporting material for reviewer depth. They are
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# SBOM Diff as a Bounded Policy Review Artifact
2+
3+
An SBOM diff can answer a useful, limited question: what dependency evidence
4+
changed between two inputs? It cannot decide whether a package is safe.
5+
6+
`sbom-diff-and-risk` keeps those statements separate. The tool produces a
7+
deterministic component diff, local heuristic risk findings, and optional
8+
policy decisions. Each layer remains visible in JSON, Markdown, SARIF, summary,
9+
and policy-sidecar artifacts.
10+
11+
## Diff evidence comes first
12+
13+
The diff layer identifies added, removed, and changed components from
14+
CycloneDX, SPDX, or supported dependency manifests. Component identity and
15+
signature fields determine membership in those sets. They are not reputation
16+
signals.
17+
18+
The local risk layer can attach bounded review buckets such as `new_package`,
19+
`major_upgrade`, `version_change_unclassified`, `unknown_license`,
20+
`suspicious_source`, and `not_evaluated`. The
21+
[risk model boundary](../../../docs/risk-model-boundary.md) defines the exact
22+
inputs for those buckets and the conclusions they do not support.
23+
24+
For example, `new_package` means a component appears only in the after input.
25+
It does not mean the package is vulnerable or malicious. `not_evaluated`
26+
preserves an unanswered question instead of filling an evidence gap with a
27+
guess.
28+
29+
## Policy is a separate decision layer
30+
31+
A local policy can map diff or risk evidence to `pass`, `warn`, or `fail`.
32+
Policy findings expose stable explanation fields:
33+
34+
- `decision_reason`
35+
- `policy_rule`
36+
- `severity_source`
37+
- `matched_threshold`
38+
- `observed_value`
39+
40+
Those fields let a reviewer see whether a decision came from a configured
41+
threshold, a risk bucket, or a default policy severity. They do not upgrade the
42+
decision into a dependency safety verdict. The full contract is documented in
43+
[policy decision explainability](policy-decision-explainability.md) and the
44+
[JSON report schema](report-schema.md).
45+
46+
## A small reproducible review surface
47+
48+
The checked-in examples include before/after inputs, generated reports, summary
49+
JSON, policy sidecars, and bounded policy-decision fixtures for `pass`, `warn`,
50+
`fail`, and consumer-side `needs-review`.
51+
52+
From `tools/sbom-diff-and-risk`, a reviewer can run:
53+
54+
```bash
55+
python -m pip install -e .[dev]
56+
python scripts/regenerate-example-artifacts.py --check
57+
python scripts/regenerate-example-artifacts.py --check --only requirements
58+
```
59+
60+
These checks use committed no-network examples. They verify that the examples
61+
still match the code; they do not prove that a third-party dependency is safe.
62+
The ordered evidence route is in the [reviewer path](reviewer-path.md).
63+
64+
## What remains a human decision
65+
66+
The tool can make a policy choice explicit, but it cannot decide whether that
67+
policy fits a deployment context. Reviewers still need to ask whether a
68+
threshold is appropriate, whether a missing license blocks release, whether a
69+
source allowlist is justified, and whether an evidence gap should fail a gate
70+
or remain `needs-review`.
71+
72+
The boundary is intentional: the artifact records what changed, which local
73+
rule matched, and why the configured policy responded. It does not resolve
74+
CVEs, inspect package contents for malware, infer exploitability, or certify a
75+
package as safe.

0 commit comments

Comments
 (0)