feat(cra): NIST/OWASP security golden-set crosswalk + full measure texts in CRA tab

Crosswalk (cra_security_crosswalk.py): deterministic, hand-curated CRA Annex I ->
NIST 800-53 Rev5 + OWASP Top 10:2021 mapping, the authoritative Security Golden
Set (no RAG; semantic breadth comes later via the shared Controls-API). Mapper
attaches NIST/OWASP refs per finding; golden-set completeness pinned by test
(every requirement has >=1 NIST ref). CRA tab now shows the NIST/OWASP best-
practice refs per finding and the full curated measure texts + norm references
(from measures_library_cra.go).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-06-13 21:24:53 +02:00
parent cadc34dad4
commit 43ae33975d
5 changed files with 225 additions and 45 deletions
@@ -2,6 +2,8 @@
from compliance.services.cra_finding_mapper import (
ScannerFinding, map_finding, assess_findings, assess_findings_payload,
)
from compliance.services.cra_security_crosswalk import CRA_SECURITY_CROSSWALK
from compliance.api.cra_annex_i_data import ANNEX_I_REQUIREMENTS
def test_hardcoded_credentials_cwe_maps_to_credential_requirement():
@@ -82,3 +84,31 @@ def test_empty_payload_is_safe():
r = assess_findings_payload({})
assert r["findings_total"] == 0
assert r["coverage_pct"] == 0.0
# --- Security golden-set crosswalk (NIST 800-53 + OWASP Top 10:2021) ---
def test_default_password_carries_nist_and_owasp_refs():
m = map_finding(ScannerFinding(id="g1", title="default password", cwe="CWE-259", severity="high"))
assert "IA-5" in m.nist_refs
assert any(o["code"] == "A07:2021" for o in m.owasp_refs)
def test_dependency_finding_maps_to_owasp_a06_and_nist_ra5():
m = map_finding(ScannerFinding(id="g2", title="outdated dependency", category="dependency", severity="high"))
assert "RA-5" in m.nist_refs
assert any(o["code"] == "A06:2021" for o in m.owasp_refs)
def test_unmapped_finding_has_no_security_refs():
m = map_finding(ScannerFinding(id="g3", title="zzz nothing", severity="low"))
assert m.nist_refs == [] and m.owasp_refs == []
def test_golden_set_covers_every_requirement():
# Completeness invariant: every CRA-AI requirement has a crosswalk entry
# with at least one NIST control id (OWASP may be empty for process reqs).
for req in ANNEX_I_REQUIREMENTS:
rid = req["req_id"]
assert rid in CRA_SECURITY_CROSSWALK, "missing crosswalk for {}".format(rid)
assert CRA_SECURITY_CROSSWALK[rid]["nist"], "no NIST refs for {}".format(rid)