Skip to content

security: fix CodeQL js/xss-through-dom findings [CTO-4840/4841/4842/4843]#302

Open
tech-sushant wants to merge 5 commits into
mainfrom
security/codeql-xss-through-dom-fixes
Open

security: fix CodeQL js/xss-through-dom findings [CTO-4840/4841/4842/4843]#302
tech-sushant wants to merge 5 commits into
mainfrom
security/codeql-xss-through-dom-fixes

Conversation

@tech-sushant
Copy link
Copy Markdown

@tech-sushant tech-sushant commented May 19, 2026

Summary

Closes 4 CodeQL XSS findings raised today (2026-05-19), all of rule `js/xss-through-dom`:

Ticket File Line CodeQL
CTO-4840 `templates/global_layout.html` 256 #79
CTO-4841 `templates/global_layout.html` 234 #78
CTO-4842 `templates/EnigmaOps/allUserAccessList.html` 141 #77
CTO-4843 `static/files/js/front.js` 141 #76

What changed

`templates/global_layout.html` (CTO-4840, CTO-4841)

Two `` patterns. Replaced with a helper that only navigates if the value is a same-origin relative path (starts with `/` but not `//`). Blocks `javascript:`/`data:` URIs and off-origin redirects.

`templates/EnigmaOps/allUserAccessList.html` (CTO-4842)

`title_line.html(title_html)` was being fed strings concatenated from the JS `access_type` variable. Rebuilt the title with jQuery element-creation APIs (`.text()` instead of `.html()`) so `access_type` is treated as text. Used `{{username|escapejs}}` to safely embed the Django value in the JS literal.

`static/files/js/front.js` (CTO-4843)

`$("#colour").change()` concatenated `$(this).val()` into a CSS path and assigned to a ``. Added a regex allowlist (`^[a-zA-Z0-9_-]+$`) on the theme name before any assignment — blocks tampered values pointing to off-origin stylesheets or `javascript:` URIs.

Why this approach

Each is a small, surgical, OSS-friendly fix — no monkey-patches, no environment flags, no surprises for downstream forks. CodeQL alerts close because the data no longer flows from text into an HTML/navigation sink.

Test plan

🤖 Generated with Claude Code

…4843]

Four CodeQL alerts for the same rule (js/xss-through-dom) flagged on
2026-05-19. Each location takes DOM-derived text and routes it into a
sink that interprets it as HTML or as a navigation target. None of
these are remote-exploitable in normal flow — the source values come
from server-rendered Django templates — but a tampered <option value>
or a malicious group name flowing through the URL builder can
escalate to script execution. Cheap fixes, low risk.

templates/global_layout.html  (CTO-4840, CTO-4841)
  Two <button onclick="javascript:location.href=document.getElementById(...).value">
  patterns. Replaced with a helper navigateToSelectedGroup(selectId)
  that only navigates if the value is a same-origin relative path
  (starts with `/` but not `//`). Blocks `javascript:`/`data:` URIs
  and off-origin redirects.

templates/EnigmaOps/allUserAccessList.html  (CTO-4842)
  title_line.html(title_html) was being fed strings concatenated from
  the JS variable `access_type`. Rebuilt the same title with jQuery
  element construction APIs (.text() instead of .html()) so
  access_type and the username are treated as text, not HTML. Used
  {{username|escapejs}} to safely embed the Django value in the JS
  literal.

static/files/js/front.js  (CTO-4843)
  $("#colour").change() concatenated $(this).val() into a CSS path
  that was then assigned to a <link href>. A tampered <option value>
  could swap the stylesheet for an off-origin URL. Added a regex
  allowlist (`^[a-zA-Z0-9_-]+$`) on the theme name before assignment.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Comment thread templates/global_layout.html Fixed
…gh-dom

Replace the charAt-based path check with a URL parser + same-origin check
and reconstruct the navigation target from parsed pathname/search/hash so
the taint flow from DOM text into location.assign is broken. CodeQL did
not recognize the charAt sanitizer and re-flagged the helper at line 298
on PR #302; the URL-parser pattern is a recognized sanitizer.

Refs CTO-4840.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread templates/global_layout.html Fixed
tech-sushant and others added 3 commits May 20, 2026 19:12
Previous attempt parsed the option value through URL with a same-origin
check, but CodeQL's js/xss-through-dom query treats URL parsing as taint-
preserving and re-flagged the navigation. Cut the DOM-text flow entirely:
emit two JS arrays of `{% url %}` outputs at render time and look up by
the dropdown's selectedIndex (a number, not text). The string passed to
location.assign is now a source-code literal.

Refs CTO-4840.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bare {% url %} output relies on Django's default HTML autoescape, which
turns `&` into `&amp;` — fine for the current routes but would corrupt
any future URL containing query params when read back by location.assign.
Capture each URL into a Django var and apply |escapejs so the value is
correctly escaped for a JS string literal regardless of what the named
route renders later.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
enigma is a public OSS repo; the inline CTO-* references add no value
for external readers. The CodeQL rule name in the comment is enough.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants