Executive brief
Unhead is a JavaScript library used by Nuxt to safely render user-supplied content in HTML `<head>` tags. This vulnerability allows attackers to bypass safety checks by encoding dangerous protocol schemes (like `javascript:` and `data:`) using padded HTML entities, which the library fails to decode. An attacker can inject malicious links that execute arbitrary JavaScript when processed by downstream applications or browser features.
Technical details
The vulnerability is a protocol-scheme validation bypass in the `hasDangerousProtocol()` function within Unhead's safe.ts plugin. The function uses fixed-width regex patterns to decode HTML entities before checking for blocked URI schemes (javascript:, data:, vbscript:), but the regex caps are insufficient: hex entities allow only 6 digits while HTML5 permits unbounded leading zeros, and decimal entities cap at 7 digits. When an attacker supplies a padded entity exceeding these limits (e.g., `:` for `:` or `:`), the regex fails silently and leaves the entity undecoded in the output. The scheme check then fails because the string doesn't start with `javascript:`, and the raw padded entity is written to SSR output. Modern browsers decode the entity natively during rendering, reconstructing the dangerous URI. Exploitation requires downstream code consuming the link href values (common in head-management libraries, SEO tools, or browser features like iframe loading in Chrome 146+). The fix is available in version 2.1.13 and later.
Affected products
- unjs Unhead < 2.1.13 (all versions up to and including 2.1.12)
Timeline
- 2026-03-22: disclosed: Disclosed to Vercel via HackerOne
- 2026-04-03: other: Cross-reported to GitHub Advisory Database
- 2026-04-09: advisory
- 2026-04-09: patched: Fixed in version 2.1.13