Repository navigation
fix(sbom): enforce SemVer evidence for risk decisions - #120
Merged
Merged
Conversation
Signed-off-by: stacknil <219124580+stacknil@users.noreply.github.com>
Signed-off-by: stacknil <219124580+stacknil@users.noreply.github.com>
Signed-off-by: stacknil <219124580+stacknil@users.noreply.github.com>
stacknil
marked this pull request as ready for review
October 21, 2026 16:33
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On main at
f7f9cae1e0ff718225677160fd59a7922ececaca, version-risk admission disagrees with the documented strict SemVer heuristic. From1.2.3:2.0.0-01,2.0.0-alpha..1, non-ASCII core digitsmajor_upgradeversion_change_unclassified2.0.0-rc.1+build.01version_change_unclassifiedmajor_upgradePURL-only and explicit evidence reproduce the same issue. Aggregate risk counts can remain unchanged while major findings are attributed to the wrong component.
Invariant
A major-upgrade finding requires two known, unequal canonical versions with eligible syntax and a strictly higher major. Unknown evidence, equal versions, decreases and same-major transitions cannot prove a major upgrade. Risk remains a local change heuristic, distinct from policy enforcement and SARIF projection.
Design decision
Validate full ASCII SemVer 2.0.0 core, prerelease and build grammar. Preserve the established outer-whitespace and lowercase-
vwrappers. Compare validated major digit strings by numeric magnitude, avoiding Python's decimal-conversion limit without changing interpreter settings.The independent test oracle decomposes delimiters and checks characters/leading zeroes from the SemVer 2.0.0 grammar; it never calls the production regex, parser helpers or classifier. Literal eligibility anchors, transition controls and exact component/rule expectations avoid count-only or circular checks. Syntax eligibility does not imply package-manager precedence.
Threat/failure model
Malformed version evidence can create a confident major finding, while valid combined suffixes lose that finding. Existing policy rules can then block the wrong component or return the wrong exit code. Oversized valid major evidence can prevent report completion. This change does not infer vulnerability, advisory, CVE, reputation or actual API compatibility information.
Rejected alternatives
Compatibility
Only corrected risk admission changes consumer outcomes. Existing
major_upgradeandversion_change_unclassifiedrules may exchange matches, block exits andpolicy_matchedconfidence as shown above. Warnings and ignored matches retain exit 0. A suppressed major policy match can retain its independent SARIFnote, without active policy escalation. Unclassified risks remain intentionally unmapped to SARIF.Canonicalization, versionless keys, fail-closed conflicts/duplicates, raw component fields/evidence, unknown handling, schema IDs/legacy fields, ordering and offline defaults remain unchanged. No dependencies, examples/goldens, workflows, release notes, tags or release assets change. This candidate has not shipped in v1.1.0.
Validation
--checkpass.pip checkclean, Ruff correctness and formatting/syntax checks pass.--check, existing schema/golden/truncation tests and both-format fail-closed conflict checks pass; no reviewed examples were overwritten.pip checkand example--checkpass in a fresh venv with socket guard. Source/temp files are on a Windows-backed mount; pytest used--capture=sysafter fd capture failed before collection. This does not establish native POSIX filesystem behavior.Changed files:
tools/sbom-diff-and-risk/src/sbom_diff_risk/risk.pytools/sbom-diff-and-risk/tests/test_version_decisions.pytools/sbom-diff-and-risk/tests/test_version_decision_reports.pytools/sbom-diff-and-risk/docs/dependency-risk-heuristics.mdFour read-only review roles found no material regressions, security/privacy issues, reliability issues or contract/coverage gaps. Finite adversarial probes do not constitute an exhaustive complexity proof.
Rollback
Revert the three contribution commits together; no migration, data rewrite or configuration rollback is required.
Review hold: Draft; do not merge for at least 24 hours after PR creation. Corrected risk admission can change security-relevant local policy outcomes. Separate merge authorization is required; no auto-merge.
Commits
24c8e462e72ad790bb248977bebb1a945a8a1bd8— fix(sbom): validate SemVer risk evidence strictly33744da3e283a77c28e91f6dd8c0824849756fae— test(sbom): compare version risks with an independent oracle279cb5db07370a2b49c3ff9f8c51374039696b17— test(sbom): lock policy and report decision projectionsMinimum review hold ends 2026-10-21 20:37:04 SGT (UTC+08:00). Keep this PR Draft and unmerged; expiry does not authorize merging.