Skip to content

fix(security): resolve CodeQL alerts on develop→staging - #37

Merged
JSisques merged 2 commits into
developfrom
fix/codeql-security-alerts
Aug 28, 2026
Merged

fix(security): resolve CodeQL alerts on develop→staging#37
JSisques merged 2 commits into
developfrom
fix/codeql-security-alerts

Conversation

@JSisques

Copy link
Copy Markdown
Contributor

Summary

CodeQL was failing on #2 (develop → staging) with 8 new alerts (7 high, 1 medium). This fixes the real issues and documents the two remaining well-formedness parses as non-exploitable.

  • js/biased-cryptographic-random (generate-random-port): modulo on crypto.getRandomValues biased low ports; replaced with rejection sampling.
  • js/incomplete-html-attribute-sanitization (convert-xml-json): escapeXml didn't escape "/', letting a JSON value break out of a generated XML attribute; now escapes them.
  • js/bad-tag-filter (format-xml): the comment-detection regex used . without dotAll, so XML comments spanning multiple lines weren't recognized as comments (broke indentation, and is exactly the kind of filter bypass CodeQL flags); fixed with [\s\S].
  • js/xss-through-dom × 2 (svg-placeholder-panel via generate-svg-placeholder): backgroundColor/textColor were interpolated unescaped into SVG attributes that get rendered via dangerouslySetInnerHTML — a real DOM XSS (e.g. "/><script>...). Now escaped like text already was.
  • js/xss-through-dom (base64-file-panel): the download link's href was set directly from the raw pasted text; rebuilt it from the already-validated mimeType/base64 parts so the URL scheme can never be attacker-controlled.
  • js/xss-through-dom × 3 (convert-xml-json ×2, format-xml ×1, both isWellFormed well-formedness checks): the parsed DOMParser Document is only used to read tagName/attributes/textContent into plain JSON/text — it's never inserted into the live DOM, so there's no actual sink downstream (output is rendered as a React text child, which auto-escapes). Suppressed with an inline codeql[js/xss-through-dom] comment explaining why, per GitHub's suppression mechanism.

Regression tests were added for every fix (attribute escaping, SVG color escaping, multi-line XML comments, rejection-sampling behavior via a mocked crypto.getRandomValues, and the rebuilt download href).

Test plan

  • pnpm test — 754 tests passing (5 new)
  • pnpm lint
  • pnpm build (astro check + build)
  • CodeQL check passes on this PR

- generate-random-port: replace modulo-biased random port selection
  with unbiased rejection sampling over crypto.getRandomValues
- convert-xml-json: escape double/single quotes in generated XML
  attribute values to prevent attribute injection
- format-xml: fix comment-detection regex to match comments spanning
  multiple lines
- generate-svg-placeholder: escape backgroundColor/textColor before
  interpolating them into SVG attributes rendered via
  dangerouslySetInnerHTML, closing a DOM XSS vector
- base64-file-panel: rebuild the download link's data URL from the
  validated mimeType/base64 parts instead of the raw pasted text
- suppress the remaining js/xss-through-dom findings on the
  well-formedness DOMParser.parseFromString calls, which only read
  tagName/attributes/textContent into plain values and never insert
  parsed nodes into the live DOM
@github-actions github-actions Bot added the tests Test-only changes label Aug 28, 2026
CodeQL still flagged the previous fix (rebuilding the data: URL from
validated parts) because the taint tracker follows the mimeType/base64
match groups through the template literal regardless of the hardcoded
scheme prefix. Decode the payload into a Blob and download it via
URL.createObjectURL instead, matching the pattern already used by
DownloadButton — the anchor's href is then a browser-generated
blob: URL with no path for user-controlled text to reach it at all.
@JSisques
JSisques merged commit 98f4d39 into develop Aug 28, 2026
9 checks passed
@JSisques
JSisques deleted the fix/codeql-security-alerts branch August 28, 2026 08:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tests Test-only changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants