Repository navigation
fix(webapp): close js/xss on the framework-control deep link - #91
Merged
Merged
Conversation
Port of GenAI-Security-Project/GenAI-Data-Security-Initiative#63 (squash 17f37f5), which fixed the same code in that repo's former crosswalk/ copy. The #/frameworks/<fw>/<control> hash route (fwControlMatch) passed URL-decoded text straight into renderControlDetail, which hands it to el() and on to appendChild. The sibling frameworkMatch route already allow-lists its input against FRAMEWORKS; this one did not. - resolveControlId() resolves the control id against the same three sources renderControlDetail reads (framework registry, backlink index, DATA mappings) and returns the stored string. The route checks the framework name against FRAMEWORKS and renders only the resolved values, never URL text. Unresolved links fall through to the frameworks index. Map lookups use hasOwnProperty so prototype keys never match. - el() routes children through toNode(), so anything that is not a DOM node is appended as a text node and can never be parsed as markup. Verified: every deep link the app builds from backlinks.js (1159), frameworks-registry.js (1514), data.js mappings (1159) and classifier-predictions.js (199) still resolves to itself; XSS payloads and __proto__/constructor resolve to null; validate, generate (no drift beyond date headers), stats:check and 50/50 unit tests match main. Co-authored-by: emmanuelgjr <129134995+emmanuelgjr@users.noreply.github.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KJVKF6raJCNKBWjTkDSqR4
emmanuelgjr
added a commit
that referenced
this pull request
Sep 14, 2026
Conflicts were only in the four generated webapp bundles, and only in their header lines: #92 regenerated them with a `// Generated:` date that this branch removes. Resolved by re-running scripts/generate.js on the merged sources; a second run is byte-identical. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014SfR2YzLxRH54DAVzDk8gR
emmanuelgjr
added a commit
that referenced
this pull request
Sep 14, 2026
No conflicts. Generated files re-run on the merged sources; a second generation is byte-identical. validate 0 errors, 60/60 tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014SfR2YzLxRH54DAVzDk8gR
emmanuelgjr
added a commit
that referenced
this pull request
Sep 14, 2026
Generated files re-run on the merged sources; a second generation is byte-identical. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014SfR2YzLxRH54DAVzDk8gR
emmanuelgjr
added a commit
that referenced
this pull request
Sep 14, 2026
Generated files re-run on the merged sources; a second generation is byte-identical. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014SfR2YzLxRH54DAVzDk8gR
emmanuelgjr
added a commit
that referenced
this pull request
Sep 14, 2026
Generated files re-run on the merged sources; a second generation is byte-identical. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014SfR2YzLxRH54DAVzDk8gR
emmanuelgjr
added a commit
that referenced
this pull request
Sep 14, 2026
Generated files re-run on the merged sources; a second generation is byte-identical. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014SfR2YzLxRH54DAVzDk8gR
emmanuelgjr
added a commit
that referenced
this pull request
Sep 14, 2026
Re-key Otto Sulin's LLM Top 10 x AISVS mapping from the 2025 list to the 2026 list per MIGRATION.md: sections renumbered and renamed, cross- references renumbered, severities re-baselined. Add eight requirements for the 2026 scope changes: LLM01 cross-modal (2.2.3, 2.2.4), LLM04 artifact provenance (3.1.1, 3.1.3), LLM05 fine-tuning subversion (6.1.2, 3.5.1), LLM08 hidden context (10.2.4), LLM10 generated code (9.3.7). Merge main (#91, #92) and regenerate entries, backlinks, bundles and stats: 3,803 mappings, 77 mapping files, 26 frameworks. Co-authored-by: Otto Sulin <ottosulin@users.noreply.github.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KJVKF6raJCNKBWjTkDSqR4
emmanuelgjr
added a commit
that referenced
this pull request
Sep 15, 2026
Generated files re-run on the merged sources; a second generation is byte-identical. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014SfR2YzLxRH54DAVzDk8gR
emmanuelgjr
added a commit
that referenced
this pull request
Sep 15, 2026
No conflicts. The one intermittent local test failure seen during verification is the pre-existing data/entries read/write race (Unexpected end of JSON input), fixed by #87; captured and confirmed, not caused by this merge. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014SfR2YzLxRH54DAVzDk8gR
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
Closes a DOM XSS (CodeQL
js/xssclass) on the framework-control deep link indocs/index.html, the hand-maintained single-page app (scripts/generate.jsonly writes thedocs/*.jsdata bundles, so this edit is not regenerated away).Why: the taint flow
The sibling
frameworkMatchroute immediately below already allow-lists its input withFRAMEWORKS.indexOf(fwName) !== -1. ThefwControlMatchbranch had no equivalent.No code-scanning analysis exists on this repo yet (
code-scanning/alertsreturnsno analysis found), so there are no alert numbers to reference here; the same flow was flagged as alerts #3 and #4 in the monorepo.Changes
resolveControlId(fwName, controlId)looks the control id up in the same three placesrenderControlDetailreads (framework registry, backlink index,DATAmappings) and returns the stored string. The route checks the framework name againstFRAMEWORKS, then renders only the resolved values, never URL text. A link that resolves to nothing falls through to the frameworks index. Adapted for this repo: the registry and backlink lookups usehasOwnProperty, so prototype keys can never match.el()only appends real nodes. Children go throughtoNode(), which returns a DOM node unchanged and wraps anything else in a text node. Before, a string inside an array madeappendChildthrow.An exact allow-list from our own data is used instead of a character filter. Control ids are full of punctuation (
GV-1.7,Art. 24-27,A.5.1), and CodeQL does not treat a negated character-class check as a sanitizer.Verification
<script>parses withvm.Script: 0 syntax errors.backlinks.jsframeworks-registry.jscontrols (incl. parent/child links)data.jsmappingsclassifier-predictions.js(review page)nulland fall through, whether used as the control id, the framework name, or both, encoded or raw:<img src=x onerror=alert(1)>,"><svg/onload=alert(1)>,<script>alert(1)</script>,__proto__,constructor. 25 checks, 0 resolved.el()tested with a DOM shim, 7/7 pass: a string child becomestextContent; an array holding a string gives a text node and no longer throws; element identity is kept; falsy entries are skipped; a number becomes a text node.main:node scripts/validate.js: 0 errors, 84 warnings, 312 passed.npm run stats:check: current.node --test scripts/*.test.mjs: 50/50.node scripts/generate.js: the only drift is the// Generated:date header.Ported from GenAI-Security-Project/GenAI-Data-Security-Initiative#63 (that copy of crosswalk/ has since been removed)
🤖 Generated with Claude Code
https://claude.ai/code/session_01KJVKF6raJCNKBWjTkDSqR4