Description
Unhead is a document head and template manager. Prior to 2.1.13, useHeadSafe() is the composable that Nuxt's own documentation explicitly recommends for rendering user-supplied content in <head> safely. Internally, the hasDangerousProtocol() function in packages/unhead/src/plugins/safe.ts decodes HTML entities before checking for blocked URI schemes (javascript:, data:, vbscript:). The decoder uses two regular expressions with fixed-width digit caps. The HTML5 specification imposes no limit on leading zeros in numeric character references. When a padded entity exceeds the regex digit cap, the decoder silently skips it. The undecoded string is then passed to startsWith('javascript:'), which does not match. makeTagSafe() writes the raw value directly into SSR HTML output. The browser's HTML parser decodes the padded entity natively and constructs the blocked URI. This vulnerability is fixed in 2.1.13.
Published: 2026-04-09
Score: 6.1 Medium
EPSS: < 1% Very Low
KEV: No
Impact: Browser XSS Vulnerability
Action: Patch Now
AI Analysis

Impact

Unhead’s useHeadSafe() previously attempted to defend against dangerous protocols by decoding HTML entities before checking for blocked URI schemes. The decoder used fixed‑width regular expressions, which silently skipped leading‑zero padded numeric character references that exceeded the digit cap. As a result, entities such as &#x0000FEED; were left undecoded and passed to a simple startsWith('javascript:') test that failed to detect the malicious protocol. The unsafe string was then written directly to the server‑side rendered HTML, where browsers decode it natively and construct the blocked URI, allowing an attacker to execute arbitrary JavaScript in all browsers that load the page. This flaw has the same effect as a client‑side XSS flaw that can lead to session hijacking, data theft, or defacement. The weakness is a classic case of CWE‑184: Unexpected Interpretation of Parameters, where malformed input bypasses validation logic. From the information supplied, the vulnerability does not allow direct server‑side code execution; its impact is confined to the client context, enabling attackers to run scripts in the browser.

Affected Systems

The affected product is the Node.js library Unhead by the unjs organization. All releases prior to version 2.1.13 are vulnerable, including any upstream Nuxt.js projects that use useHeadSafe() to render user‑supplied content in the document head.

Risk and Exploitability

The CVSS score of 6.1 indicates a moderate severity, primarily because the attack requires the ability to inject content into the <head> area of a page. The EPSS score of less than 1% suggests a low probability of existing exploitation, and the vulnerability is not currently listed in the CISA KEV catalog. However, because the flaw enables attackers to run arbitrary JavaScript in the browsers of all users who view the affected page, the potential damage can be substantial if the content is widely accessed. The likely attack vector is the insertion of specially crafted payloads that include leading‑zero padded entities through user‑controlled fields that are passed to useHeadSafe().

Generated by OpenCVE AI on April 14, 2026 at 21:37 UTC.

Remediation

No vendor fix or workaround currently provided.

OpenCVE Recommended Actions

  • Upgrade Unhead to version 2.1.13 or later.

Generated by OpenCVE AI on April 14, 2026 at 21:37 UTC.

Tracking

Sign in to view the affected projects.

Advisories
Source ID Title
Github GHSA Github GHSA GHSA-95h2-gj7x-gx9w Unhead has a hasDangerousProtocol() bypass via leading-zero padded HTML entities in useHeadSafe()
History

Tue, 14 Apr 2026 20:15:00 +0000

Type Values Removed Values Added
CPEs cpe:2.3:a:unjs:unhead:*:*:*:*:*:node.js:*:*

Mon, 13 Apr 2026 16:15:00 +0000

Type Values Removed Values Added
Metrics ssvc

{'options': {'Automatable': 'no', 'Exploitation': 'poc', 'Technical Impact': 'partial'}, 'version': '2.0.3'}


Fri, 10 Apr 2026 09:00:00 +0000

Type Values Removed Values Added
First Time appeared Unjs
Unjs unhead
Vendors & Products Unjs
Unjs unhead

Thu, 09 Apr 2026 18:15:00 +0000

Type Values Removed Values Added
Description Unhead is a document head and template manager. Prior to 2.1.13, useHeadSafe() is the composable that Nuxt's own documentation explicitly recommends for rendering user-supplied content in <head> safely. Internally, the hasDangerousProtocol() function in packages/unhead/src/plugins/safe.ts decodes HTML entities before checking for blocked URI schemes (javascript:, data:, vbscript:). The decoder uses two regular expressions with fixed-width digit caps. The HTML5 specification imposes no limit on leading zeros in numeric character references. When a padded entity exceeds the regex digit cap, the decoder silently skips it. The undecoded string is then passed to startsWith('javascript:'), which does not match. makeTagSafe() writes the raw value directly into SSR HTML output. The browser's HTML parser decodes the padded entity natively and constructs the blocked URI. This vulnerability is fixed in 2.1.13.
Title Unhead has a hasDangerousProtocol() bypass via leading-zero padded HTML entities in useHeadSafe()
Weaknesses CWE-184
References
Metrics cvssV3_1

{'score': 6.1, 'vector': 'CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N'}


cve-icon MITRE

Status: PUBLISHED

Assigner: GitHub_M

Published:

Updated: 2026-04-13T15:38:52.507Z

Reserved: 2026-04-06T19:31:07.266Z

Link: CVE-2026-39315

cve-icon Vulnrichment

Updated: 2026-04-13T15:27:54.437Z

cve-icon NVD

Status : Analyzed

Published: 2026-04-09T18:17:01.433

Modified: 2026-04-14T20:07:35.310

Link: CVE-2026-39315

cve-icon Redhat

No data.

cve-icon OpenCVE Enrichment

Updated: 2026-04-15T16:00:07Z

Weaknesses