codeql: close js/xss-through-dom alerts #709-#714 #716-#718 - #70
Open
natechadwick-intsof wants to merge 1 commit into
Open
codeql: close js/xss-through-dom alerts #709-#714 #716-#718#70natechadwick-intsof wants to merge 1 commit into
natechadwick-intsof wants to merge 1 commit into
Conversation
natechadwick-intsof
force-pushed
the
bugfix/xss-through-dom-inline-sanitizers
branch
from
August 25, 2026 21:31
48af0be to
6f39887
Compare
natechadwick-intsof
force-pushed
the
bugfix/xss-through-dom-inline-sanitizers
branch
from
August 25, 2026 23:04
6f39887 to
7656994
Compare
9 open js/xss-through-dom alerts on delivery/common/js/views/Perc*View.js href / window.location sinks closed by routing the value through the URL constructor before the sink. PRs #60 and #62 added an in-repo percSafeUrl() helper, but .github/workflows/codeql.yml explicitly notes that GHA rejects local model-pack paths in the workflow packs: input, so GHAS does not model the in-repo helper as a sanitizer barrier. Two earlier iterations of this PR tried sanitizers CodeQL still didn't recognize: 1. inline /^\\s*(?:javascript|vbscript|data)\\s*:/i regex test on the computed href (if-reassign pattern). CodeQL's xss-through-dom library doesn't model phi-node reassignment from a RegExpTest as a barrier — the first CodeQL push still flagged all 9 sinks. 2. inline String.prototype.indexOf === -1 guard placed inside the if-true branch (safer by the JS semantics, still not recognized). CodeQL's sanitizer library tracks String.prototype.startsWith and URL-constructor patterns but the simple indexOf === -1 against a literal scheme wasn't on the recognized list for this rule in this CodeQL version — 9 sinks still flagged. This PR uses the URL constructor pattern CodeQL's xss-through-dom library explicitly recognizes: var safeUrl; try { safeUrl = new URL(href, baseURL); } catch (e) { safeUrl = null; } if (safeUrl && safeUrl.protocol !== "javascript:" && safeUrl.protocol !== "vbscript:" && safeUrl.protocol !== "data:") { sink(safeUrl.href); } else { sink("#"); } After applying this to a single sink (PercTagListView.js) the CodeQL check dropped from 9 alerts to 8, confirming the pattern is recognized. The remaining 8 sinks have been migrated to the same pattern in this push. The fallback is "/" for the two window.location sinks in PercRegistrationView.js to match the original helper's behavior; "#" for the href sinks. Changes: - delivery/common/js/views/PercBlogPostView.js: drop percSafeUrl helper; URL constructor on tagHref (#716) and categoryHref (#717). - delivery/common/js/views/PercArchiveListView.js: drop percSafeUrl helper; URL constructor on the hierarchical year href (#709), hierarchical month href (#710), and flat-list month href (#711). - delivery/common/js/views/PercCategoryListView.js: drop percSafeUrl helper; URL constructor on the parseNode href (#712). - delivery/common/js/views/PercRegistrationView.js: drop percSafeUrl helper; URL constructor on both window.location sinks (confirmation-page redirect #714, rvkey redirect #713); fallback to "/" since the original helper returned that for invalid schemes. - delivery/common/js/views/PercTagListView.js: drop percSafeUrl helper; URL constructor on the tag href (#718). - docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md: drop the 9 js/xss-through-dom rows for the alerts being fixed (#709-#714, #716-#718) plus 3 stale rows for the alerts PR #62 already closed (#707, #708, #715). The corresponding // codeql[js/xss-through-dom] sink-line markers are gone from the source, so the verify-suppressions.py greps would otherwise fail. - docs/ai-generated/tasks/8.1.x-codeql-baseline/triage.md: keep the 9 rows (alerts are still open in alerts.md until the next GHAS scan dismisses them) but update notes to describe the actual code fix and the post-fix line numbers; row count still matches alerts.md so verify-triage-inventory.py stays green. - docs/ai-generated/tasks/8.1.x-codeql-baseline/clusters.md: cluster row updated to point at this PR and note the inlined sanitizer pattern; per-alert line numbers refreshed. Verification: - node --check on each modified file syntax OK - python3 scripts/verify-suppressions.py PASS - python3 scripts/verify-triage-inventory.py PASS (9 == 9) - python3 scripts/verify-valid-fixes.py PASS - CodeQL check (single-sink test) 9 -> 8 alerts JDK 1.8.0 compatible (JS only). No CHANGELOG.md entry per AGENTS.md. > Co-Authored by MiniMax Code (MiniMax-M3) with agent mavis.
natechadwick-intsof
force-pushed
the
bugfix/xss-through-dom-inline-sanitizers
branch
from
August 25, 2026 23:09
7656994 to
9876fcf
Compare
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.
Summary
Closes 9 open
js/xss-through-domalerts (#709–#714, #716–#718) ondelivery/common/js/views/Perc*View.jshref andwindow.locationsinks by routing each computed href through theURLconstructor and gating the sink onparsedUrl.protocolnot beingjavascript:,vbscript:, ordata:. The sink then receivesparsedUrl.href(the URL object's serialized form) rather than the string-concatenated value.Background
PRs #60 and #62 added an in-repo
percSafeUrl()helper and wrapped every flagged sink in apercSafeUrl(...)call..github/workflows/codeql.ymlexplicitly notes that GHA rejects local model-pack paths in the workflowpacks:input, so GHAS does not model the in-repo helper as a sanitizer barrier. PR #62 acknowledged this and shipped sink-line// codeql[rule-id]suppressions; 9 alerts (#709–#714, #716–#718) stayed open after the merge, plus 3 (#707, #708, #715) closed because the.text()-only path through the link text removed the taint.Two earlier iterations of this PR tried inline sanitizers CodeQL still didn't recognize as barriers:
/^\s*(?:javascript|vbscript|data)\s*:/i.test(href)thenif (matches) { href = "#"; }. The first CodeQL check still flagged all 9 sinks;xss-through-domdoesn't model phi-node reassignment from aRegExpTestas a barrier.String.prototype.indexOfguard inside the safe branch —if (href.indexOf("javascript:") === -1 && ...) { sink(href); }. The 9 sinks were still flagged;indexOf === -1against a literal scheme isn't on the recognized sanitizer list for this rule in the CodeQL version GHA runs.This PR uses the pattern CodeQL's
xss-through-domlibrary explicitly recognizes: theURLconstructor + protocol check. A single-sink test (onlyPercTagListView.jsmigrated first) dropped the CodeQL check from 9 alerts to 8, confirming the pattern; the remaining 8 sinks are migrated in this push.Pattern
PercRegistrationView.jsfalls back to"/"(matching the originalpercSafeUrlhelper's behavior) becausewindow.location = "#"is not a meaningful redirect target. The other four files fall back to"#".Changes
Source (5 files, 9 sinks):
delivery/common/js/views/PercBlogPostView.js— droppercSafeUrlhelper;URLconstructor ontagHref(#716) andcategoryHref(#717).delivery/common/js/views/PercArchiveListView.js— droppercSafeUrlhelper;URLconstructor on the hierarchical year href (#709), hierarchical month href (#710), and flat-list month href (#711).delivery/common/js/views/PercCategoryListView.js— droppercSafeUrlhelper;URLconstructor on theparseNodehref (#712).delivery/common/js/views/PercRegistrationView.js— droppercSafeUrlhelper;URLconstructor on bothwindow.locationsinks (confirmation-page redirect #714, rvkey redirect #613); fallback to"/".delivery/common/js/views/PercTagListView.js— droppercSafeUrlhelper;URLconstructor ontagHref(#718).Docs:
docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md— drop the 9js/xss-through-domrows for the alerts being fixed plus 3 stale rows for the alerts PR codeql: close delivery-view residuals #705-#715 #62 already closed (#707, #708, #715). The corresponding// codeql[js/xss-through-dom]sink-line markers are gone from the source, so theverify-suppressions.pygreps would otherwise fail.docs/ai-generated/tasks/8.1.x-codeql-baseline/triage.md— keep the 9 rows (alerts are still open inalerts.mduntil the next GHAS scan dismisses them) but update notes to describe the actual code fix and the post-fix line numbers; row count still matchesalerts.mdsoverify-triage-inventory.pystays green.docs/ai-generated/tasks/8.1.x-codeql-baseline/clusters.md— cluster row updated to point at this PR and note the URL-constructor pattern; per-alert line numbers refreshed.Verification
node --checkon each modified file — syntax OKscripts/verify-suppressions.py— PASSscripts/verify-triage-inventory.py— PASS (9 == 9; 9 open + 0 ready-to-close)scripts/verify-valid-fixes.py— PASSPercTagListView.jsonly) — 9 → 8 alerts, confirming the URL-constructor pattern is recognized.JDK 1.8.0 compatible (JS only). No
CHANGELOG.mdentry perAGENTS.md.Follow-up
After this PR merges, the next CodeQL scan (push to
maintriggers.github/workflows/codeql.yml) should dismiss the 9 alerts inalerts.md. A follow-up "regenerate triage + clusters" PR (matching the pattern of #61) will then drop the 9 rows fromtriage.mdand thejs/xss-through-domrow fromclusters.md.