fix(markdown,font): sanitize HTML attributes and CSS values to prevent XSS and injection#2959
Conversation
|
|
@Dozie2001 is attempting to deploy a commit to the resend Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
2 issues found across 4 files
Confidence score: 2/5
- User-impacting security risk in
packages/markdown/src/markdown.tsx: hrefs allowjavascript:and other executable schemes, enabling XSS despite HTML escaping. - Functional regression risk in
packages/font/src/font.tsx:sanitizeCssValuestrips semicolons, which can corrupt data URLs and break embedded fonts. - Pay close attention to
packages/markdown/src/markdown.tsxandpackages/font/src/font.tsx- unsafe URL handling and data URL corruption.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/markdown/src/markdown.tsx">
<violation number="1" location="packages/markdown/src/markdown.tsx:121">
P1: Link hrefs are only HTML-escaped; dangerous schemes like `javascript:` remain valid and allow XSS. Escaping does not prevent executable URL protocols.</violation>
</file>
<file name="packages/font/src/font.tsx">
<violation number="1" location="packages/font/src/font.tsx:62">
P2: sanitizeCssValue strips semicolons from webFont.url, which corrupts valid data URLs (e.g., data:font/woff;base64,...) and other URLs that rely on semicolons, breaking embedded fonts.</violation>
</file>
Since this is your first cubic review, here's how it works:
- cubic automatically reviews your code and comments on bugs and improvements
- Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
- Add one-off context when rerunning by tagging
@cubic-dev-aiwith guidance or docs links (includingllms.txt) - Ask questions if you need clarification on any suggestion
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
|
|
||
| return `<a href="${href}" target="_blank"${ | ||
| title ? ` title="${title}"` : '' | ||
| return `<a href="${escapeHtml(href)}" target="_blank"${ |
There was a problem hiding this comment.
P1: Link hrefs are only HTML-escaped; dangerous schemes like javascript: remain valid and allow XSS. Escaping does not prevent executable URL protocols.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/markdown/src/markdown.tsx, line 121:
<comment>Link hrefs are only HTML-escaped; dangerous schemes like `javascript:` remain valid and allow XSS. Escaping does not prevent executable URL protocols.</comment>
<file context>
@@ -109,8 +118,8 @@ export const Markdown = React.forwardRef<HTMLDivElement, MarkdownProps>(
- return `<a href="${href}" target="_blank"${
- title ? ` title="${title}"` : ''
+ return `<a href="${escapeHtml(href)}" target="_blank"${
+ title ? ` title="${escapeHtml(title)}"` : ''
}${
</file context>
|
|
||
| const src = webFont | ||
| ? `src: url(${webFont.url}) format('${webFont.format}');` | ||
| ? `src: url(${sanitizeCssValue(webFont.url)}) format('${sanitizeCssValue(webFont.format)}');` |
There was a problem hiding this comment.
P2: sanitizeCssValue strips semicolons from webFont.url, which corrupts valid data URLs (e.g., data:font/woff;base64,...) and other URLs that rely on semicolons, breaking embedded fonts.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/font/src/font.tsx, line 62:
<comment>sanitizeCssValue strips semicolons from webFont.url, which corrupts valid data URLs (e.g., data:font/woff;base64,...) and other URLs that rely on semicolons, breaking embedded fonts.</comment>
<file context>
@@ -47,29 +51,28 @@ export const Font: React.FC<Readonly<FontProps>> = ({
+
const src = webFont
- ? `src: url(${webFont.url}) format('${webFont.format}');`
+ ? `src: url(${sanitizeCssValue(webFont.url)}) format('${sanitizeCssValue(webFont.format)}');`
: '';
</file context>
commit: |
Summary
Fixes 5 security vulnerabilities found in the
@react-email/markdownand@react-email/fontpackages:href—hrefin the link renderer was interpolated into HTML without any escaping, allowing attribute injection.titleattribute — Both image and linktitleattributes were inserted raw, enabling event handler injection (e.g."onmouseover=alert(1)).<script>tags would execute.fontFamily,fontStyle,fontWeight,fallbackFontFamily,webFont.url/format) were interpolated directly into<style dangerouslySetInnerHTML>without sanitization.escapeQuotes()inparse-css-in-js-to-inline-css.tsreplaced"with'(single quote entity) instead of"(double quote entity), producing incorrect CSS values.Changes
packages/markdown/src/markdown.tsxescapeHtml()utility that escapes&,<,>,",'escapeHtml()to linkhref, linktitle, imagesrc, imagealt, imagetitle, and code blocktextpackages/markdown/src/utils/parse-css-in-js-to-inline-css.ts'→"inescapeQuotes()packages/font/src/font.tsxsanitizeCssValue()that strips' ; { } \ < >characters<style>tag:fontFamily,fontStyle,fontWeight,fallbackFontFamily,webFont.url,webFont.formatpackages/markdown/src/markdown.spec.tsx"entityTest plan
@react-email/markdowntests pass with updated snapshots@react-email/fonttests pass (no snapshot changes needed)font-family: "Roobert PRO") use"not'Summary by cubic
Sanitizes markdown attributes and Font CSS values to block XSS and CSS injection. Also fixes quote escaping to use " in inline CSS.