Only render safe link URLs from blog content

Blog links come from the CMS, so a javascript: URL would run code when
clicked. Allow only http(s), mailto and relative links, and render
anything else as plain text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
leanderandClaude Opus 5.5 committed 2026-10-30 21:51:53 +01:00
1 parent d04afb3e0c
commit a1729494b4
1 file changed
+31 -10
+31 -10
View File
@@ -32,6 +32,22 @@ interface LinkValue {
href: string
}
const SAFE_LINK_PROTOCOLS = ["http:", "https:", "mailto:"]
// Links come from the CMS, so reject schemes like javascript: that would run
// code when clicked. Parsing with URL also catches tricks like leading
// whitespace or mixed case that a simple prefix check would miss
const getSafeHref = (href?: string) => {
if (!href) return null
try {
const { protocol } = new URL(href, "https://uiogaming.no")
return SAFE_LINK_PROTOCOLS.includes(protocol) ? href : null
} catch {
return null
}
}
// Render posts on first visit and cache them, instead of on every request
export async function generateStaticParams() {
return []
@@ -85,16 +101,21 @@ const components: PortableTextComponents = {
}: {
children?: React.ReactNode
value?: LinkValue
}) => (
<a
href={value?.href ?? "#"}
target="_blank"
rel="noopener noreferrer"
className={styles.link}
>
{children}
</a>
),
}) => {
const href = getSafeHref(value?.href)
if (!href) return <>{children}</>
return (
<a
href={href}
target="_blank"
rel="noopener noreferrer"
className={styles.link}
>
{children}
</a>
)
},
},
}