fix: close control_id↔registry join gap (M2) — 331→0 misses, registry-aware parser + reconciliation - #218
Merged
Merged
Conversation
…I-Act/800-218A join gap)
…'t misparsed extractSection returned to EOF for the last entry on a page, so standalone trailing sections (## … maturity, ## See also, ## Changelog) were swept into that entry and their tables misparsed as control mappings. Stop at the next ## or ### heading. Clears the residual NHI maturity/changelog leaks and the AIUC-1 version/date rows (join-misses 170 -> 99); removes ~16 spurious mappings.
… SOC2/EU-AI-Act/800-218A The old (pre-fix) parser extracted prose mapping descriptions into control_id; those got captured into 3 registries as sentence-keyed 'controls'. After the registry-aware parser fix, mappings use formal codes, orphaning the sentences. Removed only controls that are BOTH unreferenced by any mapping AND a >=6-word sentence not led by a formal code (safety-asserted: no referenced or formal-code control removed). SOC 2 212->46, EU AI Act 146->47, NIST 800-218A 53->13. Scoped to these 3 (their legit controls are all formal-code-keyed); CWE/CVE and others have unreferenced entries that may be legitimate -> deferred. Join-misses still 0; validate 0/0/385.
…ts framework registry
…y re-keying + orphan cleanup
Contributor
🛡️ OWASP GenAI Security CrosswalkThis PR modifies 18 AI-related file(s). The following OWASP GenAI risks may be relevant:
🔍 Scanned 62 changed files · Found 15 potential risks · Full crosswalk · Gap analysis |
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.
What & why
Closes the machine-readable join gap (audit finding M2): previously 331 of ~3,351 entry mappings had a
control_idthat didn't resolve to any control in its framework's registry, so the classifier's ground truth and the web-app control-level pivots couldn't link them.validate.jsnever caught this because nothing checked the join. This PR drives join-misses to 0 and adds a hard-error guard so it can't silently reopen.Built with a registry-aware parser + per-framework reconciliation. Each step gated on a new audit oracle (
scripts/audit-control-join.mjs).This is intentional and traceable, not data loss — the mapping count is unchanged (3,351) and no entry lost a mapping:
control_id, and those got captured into the registries as fake "controls"). Removed only controls that are both unreferenced by any mapping and a ≥6-word sentence not led by a formal code (safety-asserted: no referenced or formal-code control touched).CWE/CVE and other frameworks have unreferenced registry entries that may be legitimate (e.g. real CWE names) — deliberately left untouched / deferred rather than risk deleting valid content.
Changes (10 commits)
test(audit)scripts/audit-control-join.mjs— the join oracle (baseline 331)fix(generate)registry-awarecontrol_idfrom whichever column token matches the framework registry; SOC2/EU-AI-Act/800-218A → 0fix(nhi)NHI-1..10(verified vs official OWASP NHI Top 10)fix(generate)section boundextractSectionstops at the next##/###so the last entry on a page no longer swallows trailing## …/Changelog tables (this also fixed the AIUC-1 version/date rows)fix(aitg)fix(800-82)§-section codes; also separated mislabeled 800-53 control blocksfix(fedramp)fix(registry)orphan cleanupfeat(validate)control_idnot in its registry (+1 check, 386 passed)docsVerification (final whole-branch review, all pass)
node scripts/audit-control-join.mjs→ TOTAL join-misses: 0node scripts/validate.js→ 0 errors / 386 passed (was 385 + the new check)control_id→ validator errors + exit 1; restored → cleannode scripts/generate.jsidempotent (the only "diff" iscore.autocrlfCRLF noise, disproved by byte-compare)Deliberately out of scope (deferred)
generate.jsif(!controlId)wrap (functionally correct).gitattributes(*.json text eol=lf) to silence Windows CRLF noise🤖 Generated with Claude Code