CVE-2026-39315: Unhead hasDangerousProtocol bypass via padded HTML entities

CVE-2026-39315 · Severity: medium · CVSS 6.1 · Published 2026-04-09

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.

Technologies: unhead (npm). Vendors: npm, UnJS.

Quick answers

Is CVE-2026-39315 exploited in the wild?
No. Junglewise Threat Intelligence has no report of CVE-2026-39315 being exploited in the wild.
How severe is CVE-2026-39315?
Medium severity, with a CVSS score of 6.1, published 9 April 2026.
Which products and versions are affected?
unhead (npm) SEMVER:introduced=0,fixed=2.1.13.
Is there a fix for CVE-2026-39315?
Yes. unhead (npm): upgrade to 2.1.13 or later. Junglewise finds every place you run it, drafts the upgrade and applies it once you approve.
How is CVE-2026-39315 attacked?
It is attacked over the network.
Am I affected by CVE-2026-39315?
Check whether you run unhead (npm) or UnJS Unhead at an affected version. Junglewise does that check for you around the clock: connect your code, cloud and domains, and it matches new vulnerabilities like this one against what you actually run and tells you when one reaches you.

How to fix

  • unhead (npm): upgrade to 2.1.13 or later
    npm install unhead@2.1.13

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., `&#0000000058;` for `:` or `&#x000003A;`), 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)

Identifiers

  • CVE-2026-39315
  • GHSA-95h2-gj7x-gx9w

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

References

This page as Markdown. Free to reuse under CC BY 4.0 with a link back.