Finding Rules
A score alone is useless in an audit; an evidence trail is everything. The primary output of OCSA is therefore a list of findings, each carrying a rule ID, a severity, the evidence (dependency path), the concrete obligation and a recommended action.
Rule catalogue
| Rule | Severity | Trigger |
|---|---|---|
LIC-001 | CRITICAL | Component is strong or network copyleft |
LIC-003 | HIGH | License unresolved — NOASSERTION, empty, or no extracted text |
LIC-004 | CRITICAL / HIGH | Custom LicenseRef- text contains copyleft indicators |
LIC-005 | HIGH / MEDIUM | Incompatible license pair within one distributed unit |
LIC-006 | CRITICAL | Copyleft propagates into a distributed unit |
LIC-007 | MEDIUM | Multi-licensed (OR) — the election must be documented |
LIC-008 | MEDIUM | Copyright text missing or NOASSERTION |
LIC-009 | HIGH | LGPL linked without a declared relinking mechanism |
LIC-002is reserved but not implemented — its intended behaviour (weak copyleft static link) is covered by LIC-009. Never renumber existing rule IDs: findings are referenced in reports and in waiver registers.
Propagation rules
| Condition | Consequence | Finding |
|---|---|---|
| Strong copyleft + static or undeclared linkage into a distributed unit | The combined work is a derivative work | LIC-006 CRITICAL |
| Strong copyleft + dynamic linkage | Separate work; confirm replaceability | LIC-006 HIGH (reported) |
| Weak copyleft (LGPL) + static or undeclared linkage | A relinking mechanism is required | LIC-009 HIGH |
| Weak copyleft + dynamic linkage | No finding | — |
| Any copyleft ancestor | Ancestor marked tainted (ring in the graph) | — |
Why the walk goes upward
The algorithm walks up from the copyleft component, not down from the root. Only copyleft components initiate a walk, so a BOM with 5 % copyleft performs 5 % of the traversals a root-down search would.
Why taint and findings are decoupled
Every ancestor is marked tainted, so the graph can draw the ring and the inventory can show inherited risk — but findings are emitted only at the distributed-unit root. The first implementation emitted a finding per hop and produced 22 identical CRITICAL entries for a single AGPL component. That is BUG-06. No information is lost: the taint chain is still visible in the detail panel, but the findings list stays actionable.
Cycle safety
Hand-maintained SBOMs regularly contain A DEPENDS_ON B and B DEPENDS_ON A. The BFS tracks
best-known hop distance per node and refuses to revisit, so the walk terminates.
Structure of a finding
{
id: 'F-042',
rule: 'LIC-006',
severity: 'CRITICAL',
title: 'Strong copyleft from "busybox" propagates into "IVI-HMI-Application"',
component: 'IVI-HMI-Application',
componentId: 'SPDXRef-Pkg-IVI-HMI-Application',
detail: 'busybox (GPL-2.0-only) → IVI-HMI-Application, linkage not declared',
obligation: 'Provide complete corresponding source of the derivative work under the same license',
action: 'Confirm linkage with the supplier; if static, either replace the component or plan source disclosure'
}
Finding is immutable and self-contained: every field needed to act on it is in the finding
itself. That is what makes findings the unit of export, of diffing, and — in Phase 2 — of waiver.
The title names the source component. The first implementation used identical titles for all LIC-006 findings, which made the list unusable; that was BUG-17.
Release gate criteria
A distributed unit passes when all of the following hold:
- Zero CRITICAL findings (unless an approved waiver exists — Phase 2)
- HIGH findings within the configured threshold
- Zero unresolved licenses
- SBOM quality at or above the configured minimum
Worked example
On the bundled 4.2.0 demo SBOM (42 components, 45 relationships):
Risk score: 61 (HIGH) SBOM quality: 50%
Findings: CRITICAL=13 HIGH=30 MEDIUM=8 (51 total)
Top findings:
[CRITICAL] LIC-006 Strong copyleft from "busybox" propagates into "IVI-HMI-Application"
[CRITICAL] LIC-006 Strong copyleft from "linux-kernel" propagates into "IVI-HMI-Application"
[CRITICAL] LIC-006 Strong copyleft from "eclipse-mosquitto-client" propagates into "IVI-HMI-Application"
[CRITICAL] LIC-004 Custom license text on vendor-camera-sdk shows copyleft indicators
[CRITICAL] LIC-001 Strong copyleft component: busybox
The fixture was authored to contain exactly the failure modes that matter: an AGPL component
statically linked into a proprietary telematics agent, LGPL components statically linked without
declared relinking, a NOASSERTION component, a custom LicenseRef- whose extracted text
mentions the GPL, and CDDL/EPL components that conflict with GPL in the same subtree.