Skip to content

Fix sanitize URLs to prevent stored XSS in website#9537

Open
michaelstaib wants to merge 1 commit intomainfrom
mst/website-issues
Open

Fix sanitize URLs to prevent stored XSS in website#9537
michaelstaib wants to merge 1 commit intomainfrom
mst/website-issues

Conversation

@michaelstaib
Copy link
Copy Markdown
Member

No description provided.

Copilot AI review requested due to automatic review settings April 13, 2026 03:51
<TeaserImage>
<img
src={latestBlogPost.featuredImage}
src={sanitizeImageSrc(latestBlogPost.featuredImage)}

return isHash ? (
<a href={to} {...rest}>
<a href={safeUrl} {...rest}>
) : internal ? (
prefetch === false ? (
<a href={to} {...rest}>
<a href={safeUrl} {...rest}>
</a>
) : (
<NextLink href={to} {...rest}>
<NextLink href={safeUrl} {...rest}>
)
) : (
<a href={to} target="_blank" rel="noopener noreferrer" {...rest}>
<a href={safeUrl} target="_blank" rel="noopener noreferrer" {...rest}>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds URL sanitization utilities to reduce the risk of stored XSS through unsafe link/image protocols, and applies them in shared UI components.

Changes:

  • Introduce sanitizeUrl and sanitizeImageSrc in url-helpers.ts with protocol allowlists.
  • Use sanitizeUrl in the shared Link component so rendered anchors don’t allow dangerous protocols.
  • Use sanitizeImageSrc for the latest blog post teaser image in the site header.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

File Description
website/src/utils/url-helpers.ts Adds URL/image-src sanitization helpers based on protocol allowlists.
website/src/components/misc/link.tsx Routes all link targets through sanitizeUrl before rendering.
website/src/components/layout/site/header.tsx Sanitizes the blog teaser <img src> value via sanitizeImageSrc.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +45 to +63
export function sanitizeImageSrc(src: string): string {
const trimmed = src.trim();

if (trimmed === "" || trimmed.startsWith("/")) {
return trimmed;
}

try {
const parsed = new URL(trimmed, "http://placeholder.invalid");

if (SAFE_IMG_PROTOCOLS.has(parsed.protocol)) {
return trimmed;
}
} catch {
// Malformed URL — reject.
}

return "";
}
Comment on lines 488 to 492
{latestBlogPost.featuredImage && (
<TeaserImage>
<img
src={latestBlogPost.featuredImage}
src={sanitizeImageSrc(latestBlogPost.featuredImage)}
alt={latestBlogPost.title}
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.

3 participants