VYPR
High severity8.8NVD Advisory· Published Mar 27, 2026· Updated Apr 13, 2026

CVE-2026-33943

CVE-2026-33943

Description

Happy DOM is a JavaScript implementation of a web browser without its graphical user interface. In versions 15.10.0 through 20.8.7, a code injection vulnerability in ECMAScriptModuleCompiler allows an attacker to achieve Remote Code Execution (RCE) by injecting arbitrary JavaScript expressions inside export { } declarations in ES module scripts processed by happy-dom. The compiler directly interpolates unsanitized content into generated code as an executable expression, and the quote filter does not strip backticks, allowing template literal-based payloads to bypass sanitization. Version 20.8.8 fixes the issue.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
happy-domnpm
>= 15.10.0, < 20.8.820.8.8

Affected products

1

Patches

1
5437fdf8f13a

fix: [#2113] Fixes issue where export names can be interpolated as executable code in ESM (#2113)

https://github.com/capricorn86/happy-domDavid OrtnerMar 24, 2026via ghsa
2 files changed · +18 1
  • packages/happy-dom/src/module/ECMAScriptModuleCompiler.ts+6 1 modified
    @@ -56,6 +56,11 @@ const SYNTAX_REGEXP = /(\/)|(\(|\))|({|})|(\[|\])|(\${)|(`)|(')|(")|(\n)/gm;
      */
     const IMPORT_REGEXP = /{([^}]+)}|\*\s+as\s+([a-zA-Z0-9-_$]+)|([a-zA-Z0-9-_$]+)/gm;
     
    +/**
    + * Strip invalid variable name characters regexp.
    + */
    +const VALID_VARIABLE_NAME_REGEXP = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
    +
     /**
      * Valid preceding token before a statement.
      */
    @@ -377,7 +382,7 @@ export default class ECMAScriptModuleCompiler {
     					const nameParts = part.trim().split(/\s+as\s+/);
     					const exportName = (nameParts[1] || nameParts[0]).replace(/["']/g, '');
     					const importName = nameParts[0].replace(/["']/g, '');
    -					if (exportName && importName) {
    +					if (exportName && importName && VALID_VARIABLE_NAME_REGEXP.test(importName)) {
     						exportCode.push(`$happy_dom.exports['${exportName}'] = ${importName}`);
     					}
     				}
    
  • packages/happy-dom/test/module/ECMAScriptModuleCompiler.test.ts+12 0 modified
    @@ -773,6 +773,18 @@ $happy_dom.exports['string6'] = string6;
     }`);
     		});
     
    +		it('Unsanitized export names are not interpolated as executable code (GHSA-6q6h-j7hj-3r64)', () => {
    +			const code = `export { require('child_process').execSync('id') }`;
    +
    +			const compiler = new ECMAScriptModuleCompiler(window);
    +			const result = compiler.compile('http://localhost:8080/js/app/main.js', code);
    +
    +			expect(result.imports).toEqual([]);
    +
    +			expect(result.execute.toString()).toBe(`async function anonymous($happy_dom) {
    +}`);
    +		});
    +
     		it('Handles tabs as whitespace.', () => {
     			const code = `
                     function warn(...args) {
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.