Fix XSS in Brand: sanitize dangerouslySetInnerHTML with DOMPurify#34712
Fix XSS in Brand: sanitize dangerouslySetInnerHTML with DOMPurify#34712tomohiro86 wants to merge 2 commits into
Conversation
📝 WalkthroughWalkthroughAdds DOMPurify and uses it to sanitize the Brand component's title HTML when no image is present; package.json updated to include dompurify typings; tests added to verify script/event stripping and preservation of safe HTML, including when the title is wrapped in a link. ChangesXSS Sanitization for Brand Component
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 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 `@code/core/src/manager/components/sidebar/Brand.tsx`:
- Around line 55-59: The external brand link rendered by LogoLink uses
target={targetValue} and can open user-configured URLs in a new tab; update the
LogoLink props to include rel="noopener noreferrer" whenever targetValue is
"_blank" (or add rel unconditionally) to prevent opener access and noreferrer
leakage. Locate the LogoLink element in Brand.tsx (the element using href={url},
target={targetValue}, dangerouslySetInnerHTML={{ __html: sanitizedTitle }}) and
add the rel attribute accordingly so external links opened with _blank are
hardened.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ebbbb806-6051-4ef9-99e5-2fca337cebf7
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (3)
code/core/package.jsoncode/core/src/manager/components/sidebar/Brand.tsxcode/core/src/manager/components/sidebar/__tests__/Brand.test.tsx
Prevents opener access and referrer leakage for external brand links.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
code/core/src/manager/components/sidebar/Brand.tsx (1)
49-49: 💤 Low valueConsider narrowing the DOMPurify allowlist for brand titles.
The default DOMPurify config is secure, but it allows a broad set of elements (e.g.,
<a>,<img>,<table>). Since brand titles are expected to contain only inline formatting, an explicitALLOWED_TAGSlist scopes the permitted surface more tightly and makes the security contract self-documenting.♻️ Proposed stricter allowlist
- const sanitizedTitle = DOMPurify.sanitize(title); + const sanitizedTitle = DOMPurify.sanitize(title, { + ALLOWED_TAGS: ['b', 'strong', 'i', 'em', 'u', 'span', 'br', 'small'], + ALLOWED_ATTR: ['class', 'style'], + });🤖 Prompt for 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. In `@code/core/src/manager/components/sidebar/Brand.tsx` at line 49, The brand title currently uses DOMPurify.sanitize(title) with the default permissive tag set; tighten this by calling DOMPurify.sanitize with an explicit ALLOWED_TAGS array (e.g., only inline formatting like "b", "i", "em", "strong", "u", "span", "br", "code") and minimal ALLOWED_ATTR if needed, then assign the result to sanitizedTitle; update the sanitize call in Brand.tsx (reference sanitizedTitle and DOMPurify.sanitize) so only the intended inline tags are permitted.
🤖 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.
Nitpick comments:
In `@code/core/src/manager/components/sidebar/Brand.tsx`:
- Line 49: The brand title currently uses DOMPurify.sanitize(title) with the
default permissive tag set; tighten this by calling DOMPurify.sanitize with an
explicit ALLOWED_TAGS array (e.g., only inline formatting like "b", "i", "em",
"strong", "u", "span", "br", "code") and minimal ALLOWED_ATTR if needed, then
assign the result to sanitizedTitle; update the sanitize call in Brand.tsx
(reference sanitizedTitle and DOMPurify.sanitize) so only the intended inline
tags are permitted.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: b471356e-00c6-4de8-827f-80d20dac9615
📒 Files selected for processing (1)
code/core/src/manager/components/sidebar/Brand.tsx
|
Hi @tomohiro86, Due to a recent high volume of unreviewed AI-generated PRs, we are requesting verification and proof that the implemented fix actually works. Please provide a simple GIF/Video or image of how the fix works, optimally with before-and-after comparisons. Thank you for your understanding! |
|
Hi @tomohiro86, We requested verification that this PR works as intended, but haven't received a response in over two weeks. We're closing this PR for now. If you'd like to continue working on this, feel free to reopen the PR with the requested verification (a GIF/video or screenshot showing before-and-after behavior). Thank you for your contribution! |
Summary
Fixes #34690
When
theme.brand.imageisnull,Brand.tsxrenderstheme.brand.titleviadangerouslySetInnerHTMLto allow custom HTML markup. A crafted theme (e.g. via a compromised addon) could use this to execute arbitrary scripts in the Storybook Manager.dompurifyas a dependencytitlewithDOMPurify.sanitize()before passing todangerouslySetInnerHTML— strips<script>tags and event handlers while preserving safe formatting HTMLBrand.test.tsxcovering XSS payloads and safe HTML pass-throughTest plan
yarn vitest run code/core/src/manager/components/sidebar/__tests__/Brand.test.tsxpassesSummary by CodeRabbit
Security
Tests