VYPR
Critical severityNVD Advisory· Published Nov 6, 2024· Updated Apr 15, 2026

CVE-2024-51757

CVE-2024-51757

Description

happy-dom is a JavaScript implementation of a web browser without its graphical user interface. Versions of happy-dom prior to 15.10.2 may execute code on the host via a script tag. This would execute code in the user context of happy-dom. Users are advised to upgrade to version 15.10.2. There are no known workarounds for this vulnerability.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
happy-domnpm
< 15.10.215.10.2

Patches

2
d23834c232f1

fix: [#1585] Fixes a security vulnerability that allowed for server side code to be executed by a <script> tag (#1588)

https://github.com/capricorn86/happy-domDavid OrtnerNov 6, 2024via ghsa
2 files changed · +6 7
  • packages/happy-dom/src/fetch/utilities/SyncFetchScriptBuilder.ts+3 1 modified
    @@ -44,7 +44,9 @@ export default class SyncFetchScriptBuilder {
     									null,
     									4
     								)};
    -                const request = sendRequest(\`${request.url.href}\`, options, (incomingMessage) => {
    +                const request = sendRequest(${JSON.stringify(
    +									request.url.href
    +								)}, options, (incomingMessage) => {
                         let data = Buffer.alloc(0);
                         incomingMessage.on('data', (chunk) => {
                             data = Buffer.concat([data, Buffer.from(chunk)]);
    
  • packages/happy-dom/test/fetch/SyncFetch.test.ts+3 6 modified
    @@ -252,8 +252,7 @@ describe('SyncFetch', () => {
     		it('Should not allow to inject code into scripts executed using child_process.execFileSync().', () => {
     			browserFrame.url = 'https://localhost:8080/';
     
    -			const url =
    -				"https://localhost:8080/`+require('child_process').execSync('id')+`/'+require('child_process').execSync('id')+'";
    +			const url = `https://localhost:8080/\`+require('child_process').execSync('id')+\`/'+require('child_process').execSync('id')+'/?key="+require('child_process').execSync('id')+"`;
     			const responseText = 'test';
     
     			mockModule('child_process', {
    @@ -267,7 +266,7 @@ describe('SyncFetch', () => {
     					expect(args[1]).toBe(
     						SyncFetchScriptBuilder.getScript({
     							url: new URL(
    -								"https://localhost:8080/%60+require('child_process').execSync('id')+%60/'+require('child_process').execSync('id')+'"
    +								`https://localhost:8080/\`+require('child_process').execSync('id')+\`/'+require('child_process').execSync('id')+'/?key="+require('child_process').execSync('id')+"`
     							),
     							method: 'GET',
     							headers: {
    @@ -280,11 +279,9 @@ describe('SyncFetch', () => {
     							body: null
     						})
     					);
    -					// new URL() will convert ` into %60
    -					// By using ` for the URL string within the script, we can prevent the script from being injected
     					expect(
     						args[1].includes(
    -							`\`https://localhost:8080/%60+require('child_process').execSync('id')+%60/'+require('child_process').execSync('id')+'\``
    +							`"https://localhost:8080/%60+require('child_process').execSync('id')+%60/'+require('child_process').execSync('id')+'/?key=%22+require(%27child_process%27).execSync(%27id%27)+%22"`
     						)
     					).toBe(true);
     					expect(options).toEqual({
    
5ee0b1676d4c

fix: [#1585] Fixes security vulnerability that allowed for server side code to be executed by a <script> tag (#1586)

https://github.com/capricorn86/happy-domDavid OrtnerNov 6, 2024via ghsa
2 files changed · +68 1
  • packages/happy-dom/src/fetch/utilities/SyncFetchScriptBuilder.ts+2 1 modified
    @@ -23,6 +23,7 @@ export default class SyncFetchScriptBuilder {
     	}): string {
     		const sortedHeaders = {};
     		const headerNames = Object.keys(request.headers).sort();
    +
     		for (const name of headerNames) {
     			sortedHeaders[name] = request.headers[name];
     		}
    @@ -43,7 +44,7 @@ export default class SyncFetchScriptBuilder {
     									null,
     									4
     								)};
    -                const request = sendRequest('${request.url.href}', options, (incomingMessage) => {
    +                const request = sendRequest(\`${request.url.href}\`, options, (incomingMessage) => {
                         let data = Buffer.alloc(0);
                         incomingMessage.on('data', (chunk) => {
                             data = Buffer.concat([data, Buffer.from(chunk)]);
    
  • packages/happy-dom/test/fetch/SyncFetch.test.ts+66 0 modified
    @@ -249,6 +249,72 @@ describe('SyncFetch', () => {
     			expect(response.body.toString()).toBe(responseText);
     		});
     
    +		it('Should not allow to inject code into scripts executed using child_process.execFileSync().', () => {
    +			browserFrame.url = 'https://localhost:8080/';
    +
    +			const url =
    +				"https://localhost:8080/`+require('child_process').execSync('id')+`/'+require('child_process').execSync('id')+'";
    +			const responseText = 'test';
    +
    +			mockModule('child_process', {
    +				execFileSync: (
    +					command: string,
    +					args: string[],
    +					options: { encoding: string; maxBuffer: number }
    +				) => {
    +					expect(command).toEqual(process.argv[0]);
    +					expect(args[0]).toBe('-e');
    +					expect(args[1]).toBe(
    +						SyncFetchScriptBuilder.getScript({
    +							url: new URL(
    +								"https://localhost:8080/%60+require('child_process').execSync('id')+%60/'+require('child_process').execSync('id')+'"
    +							),
    +							method: 'GET',
    +							headers: {
    +								Accept: '*/*',
    +								Connection: 'close',
    +								Referer: 'https://localhost:8080/',
    +								'User-Agent': window.navigator.userAgent,
    +								'Accept-Encoding': 'gzip, deflate, br'
    +							},
    +							body: null
    +						})
    +					);
    +					// new URL() will convert ` into %60
    +					// By using ` for the URL string within the script, we can prevent the script from being injected
    +					expect(
    +						args[1].includes(
    +							`\`https://localhost:8080/%60+require('child_process').execSync('id')+%60/'+require('child_process').execSync('id')+'\``
    +						)
    +					).toBe(true);
    +					expect(options).toEqual({
    +						encoding: 'buffer',
    +						maxBuffer: 1024 * 1024 * 1024
    +					});
    +					return JSON.stringify({
    +						error: null,
    +						incomingMessage: {
    +							statusCode: 200,
    +							statusMessage: 'OK',
    +							rawHeaders: [],
    +							data: Buffer.from(responseText).toString('base64')
    +						}
    +					});
    +				}
    +			});
    +
    +			const response = new SyncFetch({
    +				browserFrame,
    +				window,
    +				url,
    +				init: {
    +					method: 'GET'
    +				}
    +			}).send();
    +
    +			expect(response.body.toString()).toBe(responseText);
    +		});
    +
     		it('Should send custom key/value object request headers.', () => {
     			browserFrame.url = 'https://localhost:8080/';
     
    

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

8

News mentions

0

No linked articles in our index yet.