Skip to content

πŸ›‘οΈ Sentinel: [HIGH] Fix XSS vulnerability in custom Markdown link renderer#54

Draft
AashishH15 wants to merge 1 commit into
mainfrom
sentinel-xss-fix-13949277134668210962
Draft

πŸ›‘οΈ Sentinel: [HIGH] Fix XSS vulnerability in custom Markdown link renderer#54
AashishH15 wants to merge 1 commit into
mainfrom
sentinel-xss-fix-13949277134668210962

Conversation

@AashishH15

Copy link
Copy Markdown
Member

🚨 Severity: HIGH
πŸ’‘ Vulnerability: XSS in un-sanitized Markdown links.
🎯 Impact: Attackers can inject javascript: links into notes that execute arbitrarily when clicked.
πŸ”§ Fix: Extracted sanitizeHrefUrl and applied it to the standard a tag component renderer in ui/utils/markdownUtils.tsx.
βœ… Verification: npm run preflight passes.


PR created automatically by Jules for task 13949277134668210962 started by @AashishH15

Removed `sanitizeHrefUrl` from `LatexBlock.tsx` and placed it into `markdownUtils.tsx`.
Updated the custom `a` tag rendering for Markdown to properly sanitize `href` fields to prevent Javascript execution via `javascript:` links.
@google-labs-jules

Copy link
Copy Markdown

πŸ‘‹ Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a πŸ‘€ emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request centralizes the sanitizeHrefUrl utility in markdownUtils.tsx and applies it to custom Markdown anchor tags to prevent XSS vulnerabilities. The review feedback correctly points out that using window.location.href directly can cause runtime errors in environments without a global window object (such as SSR or Node.js tests). Additionally, returning parsed.href converts relative paths to absolute URLs, which can break local routing; returning the original trimmed URL instead is recommended.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +157 to +170
export function sanitizeHrefUrl(raw: string): string {
const trimmed = raw.trim();
try {
const parsed = new URL(trimmed, window.location.href);
const safeProtocols = ["http:", "https:", "mailto:"];
if (safeProtocols.includes(parsed.protocol)) {
return parsed.href;
}
} catch {
// Not a valid URL β€” fall through
}
// Block unsafe or malformed URLs entirely
return "about:blank";
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using window.location.href directly as the base URL for parsing can cause runtime errors in environments where window is not defined (such as Server-Side Rendering (SSR) or unit testing environments like Node.js).

Additionally, returning parsed.href converts relative URLs (e.g., /about or #section) into absolute URLs based on the current window location. This can break relative routing or portability. Returning the original trimmed URL when the protocol is safe preserves relative paths while still ensuring security.

Suggested change
export function sanitizeHrefUrl(raw: string): string {
const trimmed = raw.trim();
try {
const parsed = new URL(trimmed, window.location.href);
const safeProtocols = ["http:", "https:", "mailto:"];
if (safeProtocols.includes(parsed.protocol)) {
return parsed.href;
}
} catch {
// Not a valid URL β€” fall through
}
// Block unsafe or malformed URLs entirely
return "about:blank";
}
export function sanitizeHrefUrl(raw: string): string {
const trimmed = raw.trim();
try {
const base = typeof window !== "undefined" ? window.location.href : "http://localhost";
const parsed = new URL(trimmed, base);
const safeProtocols = ["http:", "https:", "mailto:"];
if (safeProtocols.includes(parsed.protocol)) {
return trimmed;
}
} catch {
// Not a valid URL β€” fall through
}
// Block unsafe or malformed URLs entirely
return "about:blank";
}

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.

1 participant