Skip to content

fix: prevent XSS in markdown rendering and ATOM feed#1495

Merged
mattwoberts merged 4 commits intomainfrom
advisory-wm2w-gfh7-qg69-unsafe-markdown-rendering-leading-to-pot
Apr 11, 2026
Merged

fix: prevent XSS in markdown rendering and ATOM feed#1495
mattwoberts merged 4 commits intomainfrom
advisory-wm2w-gfh7-qg69-unsafe-markdown-rendering-leading-to-pot

Conversation

@mattwoberts
Copy link
Copy Markdown
Contributor

Summary

Fixes GHSA-wm2w-gfh7-qg69 — Unsafe Markdown Rendering Leading to Potential XSS.

  • Re-enable HTML entity encoding in public/services/markdown.ts — was disabled during Tiptap editor integration (commit ac36ede), but the Tiptap editor outputs markdown (configured with html: false), not HTML, so encoding </> before marked processes input is safe and necessary
  • Remove html.UnescapeString() in app/handlers/feed.go — comment content is stored as-is in the DB, so unescaping before markdown rendering needlessly converts HTML entities back to raw HTML in ATOM feed output
  • Harden SSR fallback — when DOMPurify.isSupported is false (SSR/older browsers), strip HTML tags instead of returning raw unsanitized input
  • Add XSS prevention tests — frontend tests for <script>, <img onerror>, <svg onload>, javascript: URIs; backend test verifying <script> tags are escaped in ATOM feed output

Test plan

  • Create post/comment with <script>alert(1)</script> — verify it renders as escaped text
  • Create comment with <img src=x onerror=alert(1)> — verify no JS executes
  • Check /feed/global.atom and /feed/posts/{n}.atom — verify no unescaped HTML
  • Verify Tiptap editor still works: bold, italic, links, code blocks, mentions, image upload
  • Toggle between rich text and markdown mode — verify content survives round-trip
  • Run make lint and make test

mattwoberts and others added 3 commits April 5, 2026 22:17
Re-enable HTML entity encoding that was disabled during Tiptap editor
integration (the editor outputs markdown, not HTML, so encoding is safe).
Remove dangerous html.UnescapeString call in ATOM feed comment rendering.
Add HTML tag stripping fallback for SSR when DOMPurify is unavailable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix prettier formatting for XSS test inputs array (single line, double
quotes). Fix Go test assertion — alert() text content is expected in
escaped output, only raw <script> tags should be absent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The encodeHTML function converts < and > to entities, so text like
onerror safely appears as text content inside entity-encoded tags.
Assertions now check for actual dangerous HTML elements rather than
matching harmless text content. Fix plaintext expected value for b tags.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@PratikKaran23
Copy link
Copy Markdown

Thanks for the quick fix. The pre-encoding approach before marked is solid, one suggestion: consider adding a backend test for javascript: URIs in comments to mirror the frontend coverage in feed_test.go.

@mattwoberts mattwoberts merged commit afe20c3 into main Apr 11, 2026
5 checks passed
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