[WEB-7888] fix(security): normalize href before protocol check in CustomLinkExtension (GHSA-v2vv-7wq3-8w2j)#9313
[WEB-7888] fix(security): normalize href before protocol check in CustomLinkExtension (GHSA-v2vv-7wq3-8w2j)#9313mguptahub wants to merge 2 commits into
Conversation
…tomLinkExtension (GHSA-v2vv-7wq3-8w2j)
The existing startsWith("javascript:") guard in parseHTML() and renderHTML()
is bypassable with a whitespace prefix (e.g. "\tjavascript:alert(1)"). Per the
WHATWG URL spec, browsers strip ASCII Tab/LF/CR from URL strings during parsing,
so the whitespace-prefixed href passes the guard, is rendered into the DOM
verbatim, and executes when clicked (browser strips the tab → javascript: fires).
Add isDangerousHref() helper that strips Tab/LF/CR and leading C0 controls
before the protocol check, replicating the browser's normalization. Replace
both naive startsWith checks in parseHTML() and renderHTML() with this helper.
Add a defence-in-depth guard in clickHandler.ts that rejects
javascript:/data:/vbscript: hrefs before window.open() — link.href is the
browser-resolved URL (whitespace already stripped), so a regex check there
catches any URI that bypasses the parse/render-time guards.
Co-authored-by: Plane AI <noreply@plane.so>
|
Linked to Plane Work Item(s) This comment was auto-generated by Plane |
|
React Doctor found no issues. 🎉 Reviewed by React Doctor for commit |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe custom link click handler now checks resolved href values for unsafe URI schemes before opening a new window. Matching ChangesUnsafe link scheme guard
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/editor/src/core/extensions/custom-link/helpers/clickHandler.ts`:
- Line 48: The blocked-scheme check in clickHandler.ts is narrower than the
shared URL policy used by isValidHttpUrl, so unsafe schemes like file: and
about: can still slip through. Update the href validation in clickHandler to
reuse the shared validator (preferred) or expand the scheme block to match
isValidHttpUrl’s contract, keeping the policy consistent with the existing URL
safety rules.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: a4c9bbe5-74b8-4431-bda8-df953d8baea6
📒 Files selected for processing (2)
packages/editor/src/core/extensions/custom-link/extension.tsxpackages/editor/src/core/extensions/custom-link/helpers/clickHandler.ts
…tpUrl policy Add file: and about: to the clickHandler protocol guard to match the blocked-scheme contract in isValidHttpUrl, avoiding policy drift. Co-authored-by: Plane AI <noreply@plane.so>
Summary
isDangerousHref()helper inextension.tsxthat strips ASCII Tab/LF/CR and leading C0 controls from a raw href before the protocol check, replicating the WHATWG URL spec's whitespace normalizationstartsWith("javascript:")checks inparseHTML()andrenderHTML()withisDangerousHref()— blocks whitespace-prefixed bypasses like"\tjavascript:alert(1)"clickHandler.tsthat rejectsjavascript:/data:/vbscript:protocols beforewindow.open()—link.hrefis the browser-normalized URL so this catches any edge case that slips past parse/render-time guardsSecurity context
Advisory: GHSA-v2vv-7wq3-8w2j | Severity: High | CWE-79 (Stored XSS)
CustomLinkExtensionblockedjavascript:hrefs with a naivestartsWithcheck. Per the WHATWG URL spec, browsers strip ASCII Tab (U+0009), LF (U+000A), and CR (U+000D) from URL strings before parsing — so"\tjavascript:alert(1)"passes the guard, is stored and rendered verbatim, and when a victim clicks the link the browser strips the tab and executesjavascript:alert(1)in the application's security context. A Guest-level member can author the payload via the REST API; any higher-privileged user who clicks it is compromised.Files changed
packages/editor/src/core/extensions/custom-link/extension.tsxpackages/editor/src/core/extensions/custom-link/helpers/clickHandler.tsTest plan
<a href="\tjavascript:alert(document.cookie)">click me</a>— verify the link does not execute JS when clicked in the editorjavascript:alert(1)href — verify it is still blocked (existing behaviour unchanged)https://example.comlink — verify it opens correctly#section) and mailto links still work\njavascript:and\rjavascript:variants (LF/CR prefix)Summary by CodeRabbit
javascript:,data:, andvbscript:.file:andabout:schemes.