GHSA-XFQ5-W38Q-PC2X
Vulnerability from github – Published: 2026-10-22 16:58 – Updated: 2026-10-22 16:58Impact
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.
<!-- 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.vuecomponent or page, or enablesexperimental.componentIslandsand renders<NuxtIsland>. - Exploitation requires the application to pass attacker-controlled data to
useHeadSafeinside a server island.useHeadSafecalled 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:
- Call
useHeadSafewith untrusted input from a regular component or page rather than from inside a server island. - Alternatively, validate untrusted head input against your own allowlist before passing it to
useHeadSafeinside a server island.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "nuxt"
},
"ranges": [
{
"events": [
{
"introduced": "3.13.0"
},
{
"fixed": "4.6.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-114133"
],
"database_specific": {
"cwe_ids": [
"CWE-79"
],
"github_reviewed": true,
"github_reviewed_at": "2026-10-22T16:58:00Z",
"nvd_published_at": "2026-10-21T18:17:26Z",
"severity": "MODERATE"
},
"details": "## Impact\n\n`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 `\u003cscript\u003e` tags are only kept for JSON types.\n\nWhen `useHeadSafe` is called inside a server island (a `.server.vue` component or page, or a component rendered with `\u003cNuxtIsland\u003e`), the island renderer serialises the raw input of every head entry into the island response without the option that marks it as safe input. `\u003cNuxtIsland\u003e` then pushes that input into the page\u0027s head as a regular entry, both during server rendering and when hydrating or refetching on the client.\n\nAs a result, input that `useHeadSafe` would normally strip (such as `bodyAttrs.onload` or executable `\u003cscript\u003e` 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\u0027s origin.\n\n```vue\n\u003c!-- components/AuthorMeta.server.vue --\u003e\n\u003cscript setup lang=\"ts\"\u003e\nconst { data: author } = await useFetch(\u0027/api/author\u0027)\n// author.value.head is user-authored, e.g. { bodyAttrs: { onload: \u0027...\u0027 } }\nuseHeadSafe(author.value.head)\n\u003c/script\u003e\n```\n\n## Mitigating factors\n\n- Server components are experimental. They are only active when the application defines a `.server.vue` component or page, or enables `experimental.componentIslands` and renders `\u003cNuxtIsland\u003e`.\n- 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.\n\n## Affected versions\n\n`nuxt` `\u003e=3.13.0`, when head support for server islands was introduced. Nuxt 2 is not affected.\n\n## Patches\n\nFixed in `nuxt@4.6.2`. Nuxt 3 reached end of life on 31 July 2026 and will not receive a fix.\n\nPatched releases apply Unhead\u0027s 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.\n\n## Workarounds\n\nUpgrade to `nuxt@4.6.2`. If you cannot upgrade, including on Nuxt 3:\n\n1. Call `useHeadSafe` with untrusted input from a regular component or page rather than from inside a server island.\n2. Alternatively, validate untrusted head input against your own allowlist before passing it to `useHeadSafe` inside a server island.",
"id": "GHSA-xfq5-w38q-pc2x",
"modified": "2026-10-22T16:58:00Z",
"published": "2026-10-22T16:58:00Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/nuxt/nuxt/security/advisories/GHSA-xfq5-w38q-pc2x"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-114133"
},
{
"type": "WEB",
"url": "https://github.com/nuxt/nuxt/commit/493565e99451a0f52330b1f6b979254a4a39e5d0"
},
{
"type": "PACKAGE",
"url": "https://github.com/nuxt/nuxt"
},
{
"type": "WEB",
"url": "https://github.com/nuxt/nuxt/releases/tag/v4.6.2"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Nuxt server islands render `useHeadSafe` input without sanitisation"
}
Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline
Sightings and recorded dates, grouped by day · UTC
Loading timeline…
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.