---
id: "CVE-2026-114133"
kind: "vulnerability"
aliases: ["CVE-2026-114133", "GHSA-xfq5-w38q-pc2x"]
title: "Nuxt server islands render `useHeadSafe` input without sanitisation"
severity: "medium"
cvss: 5.400000095367432
epss: 0.0017600000137463212
exploited: false
status: "open"
category: "runtime"
products: [{"name": "nuxt", "fixed": ["4.6.2"], "affected": ">= 3.13.0, < 4.6.2", "ecosystem": "npm"}]
ecosystems: ["npm"]
tags: ["cwe-79", "next.js", "nuxt", "runtime", "self-hosted", "vue"]
not_affected_if: ["default-config", "fixed-version", "no-server-islands", "nuxt-2", "static-export"]
published_at: "2026-10-21T18:17:26+00:00"
first_seen_at: "2026-10-23T19:11:31+00:00"
updated_at: "2026-10-23T21:57:29+00:00"
sources: [{"source": "ghsa", "url": "https://github.com/advisories/GHSA-xfq5-w38q-pc2x", "first_seen_at": "2026-10-23T19:11:31+00:00"}, {"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-114133", "first_seen_at": "2026-10-23T21:57:29+00:00"}]
---

# Nuxt server islands render `useHeadSafe` input without sanitisation

Nuxt server islands serialise raw useHeadSafe input without the safe-input flag, so tags and attributes that useHeadSafe would strip (such as bodyAttrs.onload or executable script content) get rendered into the page. If an app passes user-controlled data to useHeadSafe inside a server island, an attacker can run stored XSS on the app's origin.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- npm:nuxt affected >= 3.13.0, < 4.6.2 fixed 4.6.2

## How to check

Search the codebase for useHeadSafe inside .server.vue components/pages or components rendered with NuxtIsland, and check whether any of that input comes from user-controlled data (e.g. an API response that users can write to).
Check the installed nuxt version in node_modules/nuxt/package.json or your lockfile; affected if >=3.13.0 and <4.6.2.

## Fix

Upgrade nuxt to 4.6.2 or later (Nuxt 3 is end of life and will not get a fix).
Until then, call useHeadSafe with untrusted input from a regular component or page, or validate that input against your own allowlist before passing it inside a server island.

## Timeline

- 2026-10-23T19:11:31+00:00 ghsa https://github.com/advisories/GHSA-xfq5-w38q-pc2x
- 2026-10-23T21:57:29+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-114133

## From the sources

## Impact

`useHeadSafe` restricts head input to an allowlist of safe tags and attributes. For example, `bodyAttrs` is limited to `class` and `style`, event handler attributes are removed, and `<script>` tags are only kept for JSON types.

When `useHeadSafe` is called inside a server island (a `.server.vue` component or page, or a component rendered with `<NuxtIsland>`), the island renderer serialises the raw input of every head entry into the island response without the option that marks it as safe input. `<NuxtIsland>` then pushes that input into the page's head as a regular entry, both during server rendering and when hydrating or refetching on the client.

As a result, input that `useHeadSafe` would normally strip (such as `bodyAttrs.onload` or executable `<script>` content) is rendered into the page. If an application passes user-controlled data to `useHeadSafe` inside a server island, an attacker who controls that data can achieve stored cross-site scripting on the application's origin.

```vue
<!-- components/AuthorMeta.server.vue -->
<script setup lang="ts">
const { data: author } = await useFetch('/api/author')
// author.value.head is user-authored, e.g. { bodyAttrs: { onload: '...' } }
useHeadSafe(author.value.head)
</script>
```

## Mitigating factors

- Server components are experimental. They are only active when the application defines a `.server.vue` component or page, or enables `experimental.componentIslands` and renders `<NuxtIsland>`.
- Exploitation requires the application to pass attacker-controlled data to `useHeadSafe` inside a server island. `useHeadSafe` called from regular (non-island) components and pages is not affected.

## Affected versions

`nuxt` `>=3.13.0`, when head support for server islands was introduced. Nuxt 2 is not affected.

## Patches

Fixed in `nuxt@4.6.2`. Nuxt 3 reached end of life on 31 July 2026 and will not receive a fix.

Patched releases apply Unhead's safe input filtering to `useHeadSafe` entries on the server before they are added to the island response, so `islandResponse.head` (including what `render:island` hooks see) only contains input that `useHeadSafe` allows.

## Workarounds

Upgrade to `nuxt@4.6.2`. If you cannot upgrade, including on Nuxt 3:

1. Call `useHeadSafe` with untrusted input from a regular component or page rather than from inside a server island.
2. Alternatively, validate untrusted head input against your own allowlist before passing it to `useHeadSafe` inside a server island.

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
