🤖 fix: harden renderer HTML sinks against XSS#2502
Conversation
Replace attacker-controlled filename HTML rendering with safe React nodes, harden Mermaid SVG rendering with strict mode + sanitization, and document renderer XSS guardrails in AGENTS. --- _Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$0.01`_ <!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=0.01 -->
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0cd4c8ba43
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Keep Mermaid label rendering intact by preserving foreignObject nodes while continuing to strip active content and dangerous URL schemes. --- _Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$0.01`_ <!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=0.01 -->
|
@codex review Addressed the |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5a26607d76
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Decode encoded URL forms before blocked-scheme checks so obfuscated payloads like `java script:` and `java%0Ascript:` are stripped during Mermaid SVG sanitization. --- _Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$0.01`_ <!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=0.01 -->
|
@codex review Addressed encoded/obfuscated scheme bypasses by canonicalizing entity + percent-encoded URL values before blocked-scheme checks. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 442e5e4b53
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Guard numeric entity decoding against invalid Unicode code points so sanitizer canonicalization cannot throw on crafted values. --- _Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$0.01`_ <!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=0.01 -->
|
@codex review Added invalid-codepoint guards in entity decoding so sanitizer canonicalization cannot throw on crafted numeric entities. |
|
Codex Review: Didn't find any major issues. What shall we delve into next? ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
Summary
Fix renderer XSS exposure in diff and markdown diagram paths by removing unsafe filename HTML rendering in
HunkViewerand hardening Mermaid SVG insertion.Background
A filename from workspace/repository content was being transformed into HTML and injected via
dangerouslySetInnerHTMLinHunkViewer. Because filenames are attacker-controlled, this enabled immediate XSS when viewing a crafted diff. Given renderer-accessible privileged surfaces, that XSS materially increased impact.Implementation
HunkViewerwith safe React element rendering (<mark>nodes) so React escaping remains in effect.dangerouslySetInnerHTMLusage forhunk.filePathdisplay.securityLevel: "loose"to"strict"sanitizeMermaidSvg()and route all rendered SVG through it beforeinnerHTMLassignmentscript,iframe,object,embed) and stripped inline event handlers / dangerous URL schemes from URL-bearing attributesjava script:are blocked<foreignObject>nodes so Mermaid wrapped labels continue to renderSECURITY AUDITcomments at unavoidable HTML sinks to document trust boundaries.Mermaid.sanitization.test.tsto verify malformed SVG rejection, active-content stripping, encoded-scheme blocking, invalid-entity handling, and label preservation.Security: Renderer HTML & XSSsection indocs/AGENTS.mdto codify safe patterns.Validation
make static-check(before initial push)bun test src/browser/components/Messages/Mermaid.sanitization.test.tsmake static-check(after foreignObject-label follow-up)bun test src/browser/components/Messages/Mermaid.sanitization.test.tsmake static-check(after encoded-scheme canonicalization follow-up)bun test src/browser/components/Messages/Mermaid.sanitization.test.tsmake static-check(after invalid-entity guard follow-up)Risks
securityLevel: "strict"may reduce support for some diagram features that relied on looser behavior (especially scriptable/unsafe links), but this is intentional hardening.Generated with
mux• Model:openai:gpt-5.3-codex• Thinking:xhigh• Cost:$0.01