Skip to content

fix: use DOM parser for heading slug generation to prevent XSS#3290

Merged
jeanfbrito merged 1 commit intodevfrom
fix/markdown-heading-slug-sanitization
Apr 6, 2026
Merged

fix: use DOM parser for heading slug generation to prevent XSS#3290
jeanfbrito merged 1 commit intodevfrom
fix/markdown-heading-slug-sanitization

Conversation

@jeanfbrito
Copy link
Copy Markdown
Member

@jeanfbrito jeanfbrito commented Apr 6, 2026

Summary

  • Replace regex-based HTML tag stripping (/<[^>]*>/g) with document.createElement('div') + .textContent for safe text extraction in heading slug generation
  • Fixes CodeQL "Incomplete multi-character sanitization" warning flagged on Release 4.14.0 #3289

Context

The previous regex could leave partial HTML tags (e.g., <script without closing >) in the slug, which CodeQL flagged as a potential injection vector. Using the browser's DOM parser eliminates this class of vulnerability entirely.

Test plan

  • Open a markdown file with headings containing inline code, bold, links
  • Verify TOC anchor links still scroll to correct headings
  • Confirm no HTML tag names leak into heading IDs

Summary by CodeRabbit

  • Bug Fixes
    • Improved Markdown heading slug generation to more reliably handle special characters and HTML entities in heading text.

Replace regex-based HTML stripping with document.createElement +
textContent for safe text extraction. Fixes CodeQL incomplete
multi-character sanitization warning.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b035334e-ceb5-4e0c-8622-e1e6fea42ddc

📥 Commits

Reviewing files that changed from the base of the PR and between af40a4a and 9f92bb2.

📒 Files selected for processing (1)
  • src/ui/components/ServersView/MarkdownContent.tsx
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: check (windows-latest)
  • GitHub Check: check (ubuntu-latest)
  • GitHub Check: check (macos-latest)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript strict mode enabled in TypeScript configuration
Use React functional components with hooks instead of class components
Follow FSA (Flux Standard Action) pattern for Redux actions
Use camelCase for file names and PascalCase for component file names
All code must pass ESLint and TypeScript checks
Write self-documenting code with clear naming; avoid unnecessary comments except for complex business logic or non-obvious decisions
Use Fuselage components from @rocket.chat/fuselage for all UI work and only create custom components when Fuselage doesn't provide what's needed
Check Theme.d.ts for valid color tokens when using Fuselage components
Use defensive coding with optional chaining and fallbacks for Linux-only APIs (process.getuid(), process.getgid(), process.geteuid(), process.getegid()) to ensure cross-platform compatibility across Windows, macOS, and Linux

Files:

  • src/ui/components/ServersView/MarkdownContent.tsx
🧠 Learnings (1)
📓 Common learnings
Learnt from: Ram-sah19
Repo: RocketChat/Rocket.Chat.Electron PR: 3254
File: .github/workflows/build-release.yml:80-94
Timestamp: 2026-03-11T06:38:40.426Z
Learning: In the RocketChat/Rocket.Chat.Electron repository, the issues flagged in `.github/workflows/build-release.yml` (e.g., `node12` runtime in the release action and missing `snapcraft_token` input), i18n files, and `electron-builder.json` are pre-existing in the `develop` branch and are pulled in during merge conflict resolution. Do not flag these as new issues introduced by PRs that only modify `src/injected.ts` and `src/ui/main/rootWindow.ts`.
🔇 Additional comments (1)
src/ui/components/ServersView/MarkdownContent.tsx (1)

103-105: Good hardening: DOM-based text extraction is the right fix here.

This closes the partial-tag sanitization gap from regex stripping while preserving existing slug normalization behavior.


Walkthrough

The markdown heading slug generation in MarkdownContent.tsx was updated to extract heading text using a temporary DOM element with innerHTML and textContent rather than direct regex HTML stripping. The subsequent normalization pipeline and heading markup output remain unchanged.

Changes

Cohort / File(s) Summary
Markdown Slug Generation
src/ui/components/ServersView/MarkdownContent.tsx
Updated heading slug computation to use DOM createElement with textContent extraction instead of regex-based HTML tag removal for more reliable text extraction.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

type: bug

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: replacing regex-based HTML stripping with DOM parsing in heading slug generation to prevent XSS vulnerabilities.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@jeanfbrito jeanfbrito merged commit 41e65be into dev Apr 6, 2026
7 checks passed
@jeanfbrito jeanfbrito deleted the fix/markdown-heading-slug-sanitization branch April 6, 2026 17:18
@jeanfbrito jeanfbrito mentioned this pull request Apr 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant