unhead@betaThe useHeadSafe composable is a security-focused wrapper around the useHead composable that restricts input to only allow safe values, providing protection against XSS attacks when working with untrusted content.
Quick Start:
useHeadSafe({
title: userInput.title, // Automatically sanitized
meta: [{ name: 'description', content: userInput.description }]
})
The composable implements a strict whitelist of allowed tags and attributes. When you attempt to use a tag or attribute that isn't on the whitelist, it will be silently ignored to prevent potential security issues.
The security whitelist specifies which attributes are allowed for each tag type:
import { useHeadSafe } from '@unhead/angular'
// The whitelist used internally by useHeadSafe
const WhitelistAttributes = {
htmlAttrs: ['class', 'style', 'lang', 'dir'] satisfies (keyof HtmlAttributes)[],
bodyAttrs: ['class', 'style'] satisfies (keyof BodyAttributes)[],
meta: ['name', 'property', 'charset', 'content', 'media'] satisfies (keyof Meta)[],
noscript: ['textContent'] satisfies (Partial<keyof Noscript> | 'textContent')[],
style: ['media', 'textContent', 'nonce', 'title', 'blocking'] satisfies (Partial<keyof Style> | 'textContent')[],
script: ['type', 'textContent', 'nonce', 'blocking'] satisfies (Partial<keyof Script> | 'textContent')[],
link: ['color', 'crossorigin', 'fetchpriority', 'href', 'hreflang', 'imagesrcset', 'imagesizes', 'integrity', 'media', 'referrerpolicy', 'rel', 'sizes', 'type'] satisfies (keyof Link)[],
} as const
<script type="application/json">) - use textContent: myObjecthttp-equiv attribute is not allowed on meta tagsdata-* attributes are allowed on all elementsdata:, javascript:)['stylesheet', 'canonical', 'modulepreload', 'prerender', 'preload', 'prefetch']function useHeadSafe(input: UseHeadInput, options?: HeadEntryOptions): ActiveHeadEntry
The API signature is identical to useHead, but with additional security filtering applied to the input.
When working with head data from an untrusted data source:
import { useHeadSafe } from '@unhead/angular'
// Load metadata from a third-party source
const thirdPartyMeta = loadMeta()
// Safely apply the metadata
useHeadSafe(thirdPartyMeta)
When allowing users to provide custom meta tags:
import { useHeadSafe } from '@unhead/angular'
// User profile with user-defined metadata
const userProfile = await fetchUserProfile(userId)
useHeadSafe({
title: userProfile.pageTitle,
meta: [
{ name: 'description', content: userProfile.pageDescription },
...userProfile.customMetaTags // These will be filtered for safety
]
})
useHeadSafe offers protection for most XSS vectors, there are still some important security considerations:While style attributes are permitted, it's important to note that clickjacking vulnerabilities can still be introduced through malicious CSS. Always validate style content even when using useHeadSafe.
For maximum security when handling untrusted content:
useHeadSafeUse useHeadSafe() whenever you're working with untrusted or user-provided input to prevent XSS attacks.
All string values are HTML-escaped. Script tags and event handlers are stripped. Only safe attributes are allowed.