---
title: "useHeadSafe()"
description: "Safely manage head tags with XSS protection using useHeadSafe(). Sanitize untrusted user input for titles, meta tags, and other head elements."
canonical_url: "https://unhead.unjs.io/docs/head/api/composables/use-head-safe"
last_updated: "2026-05-01T14:58:24.000Z"
---

The `useHeadSafe` composable is a security-focused wrapper around the [useHead](/docs/head/api/composables/use-head) composable that restricts input to only allow safe values, providing protection against XSS attacks when working with untrusted content.

**Quick Start:**

```ts
useHeadSafe({
  title: userInput.title, // Automatically sanitized
  meta: [{ name: 'description', content: userInput.description }]
})
```

## How It Works

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.

<warning>

The whitelist is intentionally restrictive since there are many vectors for XSS attacks. If you need to use a tag or attribute that isn't on the whitelist, you can use the [useHead](/docs/head/api/composables/use-head) composable instead, but **you must sanitize the input yourself**.

</warning>

### Security Whitelist

The security whitelist specifies which attributes are allowed for each tag type:

```ts
import { useHeadSafe } from '@unhead/dynamic-import'

// 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
```

### Additional Restrictions

<note>

The following security restrictions also apply:

</note>

- Scripts of any sort are not allowed, except for JSON (`<script type="application/json">`) - use `textContent: myObject`
- `http-equiv` attribute is not allowed on meta tags
- `data-*` attributes are allowed on all elements
- Link tags will strip invalid href values (like `data:`, `javascript:`)
- Link tags don't support these rel values: `['stylesheet', 'canonical', 'modulepreload', 'prerender', 'preload', 'prefetch']`

## API Reference

```ts
function useHeadSafe(input: UseHeadInput, options?: HeadEntryOptions): ActiveHeadEntry
```

The API signature is identical to [useHead](/docs/head/api/composables/use-head), but with additional security filtering applied to the input.

## Examples

### Handling Untrusted Data

When working with head data from an untrusted data source:

```ts
import { useHeadSafe } from '@unhead/dynamic-import'

// Load metadata from a third-party source
const thirdPartyMeta = loadMeta()

// Safely apply the metadata
useHeadSafe(thirdPartyMeta)
```

### User-Generated Content

When allowing users to provide custom meta tags:

```ts
import { useHeadSafe } from '@unhead/dynamic-import'

// 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
  ]
})
```

## Security Considerations

<caution>

While `useHeadSafe` offers protection for most XSS vectors, there are still some important security considerations:

</caution>

### Styles

While style attributes are permitted, it's important to note that [clickjacking](https://en.wikipedia.org/wiki/Clickjacking) vulnerabilities can still be introduced through malicious CSS. Always validate style content even when using `useHeadSafe`.

### Best Practices

For maximum security when handling untrusted content:

1. Apply additional validation to any user inputs before passing to `useHeadSafe`
2. Consider using a dedicated content security policy (CSP)
3. Use the built-in sanitization but don't rely on it as your only defense
4. Avoid allowing custom styles when possible with untrusted content

## Common Use Cases

- Working with user-generated content
- Displaying metadata from third-party APIs
- Creating CMS systems where content editors can customize SEO fields
- Implementing white-label solutions where customers can customize branding

## Common Questions

### When should I use useHeadSafe instead of useHead?

Use `useHeadSafe()` whenever you're working with untrusted or user-provided input to prevent XSS attacks.

### What gets sanitized?

All string values are HTML-escaped. Script tags and event handlers are stripped. Only safe attributes are allowed.

## See Also

- [useHead()](/docs/head/api/composables/use-head) - General head management
- [useSeoMeta()](/docs/head/api/composables/use-seo-meta) - SEO meta tags
- [Security Considerations](/docs/head/api/composables/use-head#security-considerations)
