CVE-2021-23406 (published 2021-08-24T08:15Z)

This affects the package pac-resolver before 5.0.0. This can occur when used with untrusted input, due to unsafe PAC file handling. **NOTE:** The fix for this vulnerability is applied in the node-degenerator library, a dependency written by the same maintainer.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/TooTallNate/node-degenerator
commit_details: repo_url: https://github.com/TooTallNate/node-degenerator
author: Nathan Rajlich
author_date: 2021-07-12 14:27:04-07:00
msg: Fix `filename` option
repository: repo_url: https://github.com/TooTallNate/node-degenerator
repo_name: TooTallNate/node-degenerator
description: Turns sync functions into async functions
owner: TooTallNate
file_changes: filename: index.ts
change_type: ModificationType.MODIFY
diff: @@ -3,7 +3,7 @@ import { generate } from 'escodegen';
 import { parseScript } from 'esprima';
 import { visit, namedTypes as n, builders as b } from 'ast-types';
 import { Context, RunningScriptOptions } from 'vm';
-import { VM } from 'vm2';
+import { VM, VMScript } from 'vm2';
 
 /**
  * Compiles sync JavaScript code into JavaScript with async Functions.
@@ -138,7 +138,10 @@ namespace degenerator {
 	): (...args: A) => Promise<R> {
 		const compiled = degenerator(code, names);
 		const vm = new VM(options);
-		const fn = vm.run(`${compiled};${returnName}`);
+		const script = new VMScript(`${compiled};${returnName}`, {
+			filename: options.filename,
+		});
+		const fn = vm.run(script);
 		if (typeof fn !== 'function') {
 			throw new Error(
 				`Expected a "function" to be returned for \`${returnName}\`, but got "${typeof fn}"`

programming_language: TypeScript
filename: test.ts
change_type: ModificationType.MODIFY
diff: @@ -159,26 +159,42 @@ describe('degenerator()', () => {
 				assert.equal(val, 'foo');
 			});
 		});
-		it('should prevent privilege escalation of untrusted code', async() => {
+		it('should prevent privilege escalation of untrusted code', async () => {
 			let err;
 			try {
 				const fn = compile<typeof process>(
 					`const f = this.constructor.constructor('return process');`,
 					'f',
-					[],
+					[]
 				);
 				await fn();
-			} catch(_err) {
+			} catch (_err) {
 				err = _err;
 			}
-			assert.equal(err.message,'process is not defined')
+			assert.equal(err.message, 'process is not defined');
 		});
 		it('should allow to return synchronous undefined', () => {
 			function u() {}
 			const fn = compile(`${u}`, 'u', ['']);
-			return fn().then(val => {
+			return fn().then((val) => {
 				assert.strictEqual(val, undefined);
 			});
 		});
+		it('should support "filename" option', async () => {
+			function u() {
+				throw new Error('fail');
+			}
+			let err;
+			const fn = compile(`${u}`, 'u', [''], {
+				filename: '/foo/bar/baz.js',
+			});
+			try {
+				await fn();
+			} catch (_err) {
+				err = _err;
+			}
+			assert.strictEqual(err.message, 'fail');
+			assert(err.stack.includes('at u (/foo/bar/baz.js:'));
+		});
 	});
 });

programming_language: TypeScript
repo_url: https://github.com/TooTallNate/node-degenerator
commit_details: repo_url: https://github.com/TooTallNate/node-degenerator
author: Nathan Rajlich
author_date: 2021-07-12 14:26:21-07:00
msg: Fix return `undefined`
repository: repo_url: https://github.com/TooTallNate/node-degenerator
repo_name: TooTallNate/node-degenerator
description: Turns sync functions into async functions
owner: TooTallNate
file_changes: filename: index.ts
change_type: ModificationType.MODIFY
diff: @@ -147,7 +147,7 @@ namespace degenerator {
 		const r = function (this: any, ...args: A): Promise<R> {
 			try {
 				const p = fn.apply(this, args);
-				if (typeof p.then === 'function') {
+				if (typeof p?.then === 'function') {
 					return p;
 				}
 				return Promise.resolve(p);

programming_language: TypeScript
filename: test.ts
change_type: ModificationType.MODIFY
diff: @@ -136,7 +136,7 @@ describe('degenerator()', () => {
 				'Expected a "function" to be returned for `foo`, but got "number"'
 			);
 		});
-		it('should be compile if branches', () => {
+		it('should compile if branches', () => {
 			function ifA(): string {
 				if (a()) {
 					return 'foo';
@@ -173,5 +173,12 @@ describe('degenerator()', () => {
 			}
 			assert.equal(err.message,'process is not defined')
 		});
+		it('should allow to return synchronous undefined', () => {
+			function u() {}
+			const fn = compile(`${u}`, 'u', ['']);
+			return fn().then(val => {
+				assert.strictEqual(val, undefined);
+			});
+		});
 	});
 });

programming_language: TypeScript