- CVE-2023-39333.patch: Code injection via WebAssembly export names (CVE-2023-39333, bsc#1216273) - CVE-2023-44487.patch: nghttp2 Security Release (CVE-2023-44487, bsc#1216190) - CVE-2023-45143.patch: undici Security Release (CVE-2023-39333, bsc#1216273) OBS-URL: https://build.opensuse.org/package/show/devel:languages:nodejs/nodejs16?expand=0&rev=99
192 lines
7.4 KiB
Diff
192 lines
7.4 KiB
Diff
commit eaf9083cf1e43bd897ac8244dcc0f4e3500150ca
|
|
Author: Tobias Nießen <tniessen@tnie.de>
|
|
Date: Sun Aug 6 10:41:33 2023 +0000
|
|
|
|
module: fix code injection through export names
|
|
|
|
createDynamicModule() properly escapes import names, but not export
|
|
names. In WebAssembly, any string is a valid export name. Importing a
|
|
WebAssembly module that uses a non-identifier export name leads to
|
|
either a syntax error in createDynamicModule() or to code injection,
|
|
that is, to the evaluation of almost arbitrary JavaScript code outside
|
|
of the WebAssembly module.
|
|
|
|
To address this issue, adopt the same mechanism in createExport() that
|
|
createImport() already uses. Add tests for both exports and imports.
|
|
|
|
PR-URL: https://github.com/nodejs-private/node-private/pull/461
|
|
Backport-PR-URL: https://github.com/nodejs-private/node-private/pull/490
|
|
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
|
|
CVE-ID: CVE-2023-39333
|
|
|
|
commit 1193ca5fdb6e3eaa56b57a1b62cd48c7309b5d01
|
|
Author: Matthew Aitken <maitken033380023@gmail.com>
|
|
Date: Fri Oct 6 17:04:05 2023 -0400
|
|
|
|
lib: let deps require `node` prefixed modules
|
|
|
|
fixup
|
|
|
|
fixup
|
|
|
|
PR-URL: https://github.com/nodejs/node/pull/50047
|
|
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
|
|
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
|
|
Reviewed-By: Michaël Zasso <targos@protonmail.com>
|
|
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
|
|
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
|
|
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
|
|
Reviewed-By: Zeyu "Alex" Yang <himself65@outlook.com>
|
|
|
|
|
|
Includes wasm-fixtures.tar.gz because quilt doesn't support binary patches....
|
|
|
|
Index: node-v16.20.2/lib/internal/modules/esm/create_dynamic_module.js
|
|
===================================================================
|
|
--- node-v16.20.2.orig/lib/internal/modules/esm/create_dynamic_module.js
|
|
+++ node-v16.20.2/lib/internal/modules/esm/create_dynamic_module.js
|
|
@@ -18,13 +18,13 @@ function createImport(impt, index) {
|
|
import.meta.imports[${imptPath}] = $import_${index};`;
|
|
}
|
|
|
|
-function createExport(expt) {
|
|
- const name = `${expt}`;
|
|
- return `let $${name};
|
|
-export { $${name} as ${name} };
|
|
-import.meta.exports.${name} = {
|
|
- get: () => $${name},
|
|
- set: (v) => $${name} = v,
|
|
+function createExport(expt, index) {
|
|
+ const nameStringLit = JSONStringify(expt);
|
|
+ return `let $export_${index};
|
|
+export { $export_${index} as ${nameStringLit} };
|
|
+import.meta.exports[${nameStringLit}] = {
|
|
+ get: () => $export_${index},
|
|
+ set: (v) => $export_${index} = v,
|
|
};`;
|
|
}
|
|
|
|
Index: node-v16.20.2/test/es-module/test-esm-wasm.mjs
|
|
===================================================================
|
|
--- node-v16.20.2.orig/test/es-module/test-esm-wasm.mjs
|
|
+++ node-v16.20.2/test/es-module/test-esm-wasm.mjs
|
|
@@ -29,6 +29,56 @@ describe('ESM: WASM modules', { concurre
|
|
strictEqual(code, 0);
|
|
});
|
|
|
|
+ it('should not allow code injection through export names', async () => {
|
|
+ const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
|
+ '--no-warnings',
|
|
+ '--experimental-wasm-modules',
|
|
+ '--input-type=module',
|
|
+ '--eval',
|
|
+ `import * as wasmExports from ${JSON.stringify(fixtures.fileURL('es-modules/export-name-code-injection.wasm'))};`,
|
|
+ ]);
|
|
+
|
|
+ strictEqual(stderr, '');
|
|
+ strictEqual(stdout, '');
|
|
+ strictEqual(code, 0);
|
|
+ });
|
|
+
|
|
+ it('should allow non-identifier export names', async () => {
|
|
+ const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
|
+ '--no-warnings',
|
|
+ '--experimental-wasm-modules',
|
|
+ '--input-type=module',
|
|
+ '--eval',
|
|
+ [
|
|
+ 'import { strictEqual } from "node:assert";',
|
|
+ `import * as wasmExports from ${JSON.stringify(fixtures.fileURL('es-modules/export-name-syntax-error.wasm'))};`,
|
|
+ 'assert.strictEqual(wasmExports["?f!o:o<b>a[r]"]?.value, 12682);',
|
|
+ ].join('\n'),
|
|
+ ]);
|
|
+
|
|
+ strictEqual(stderr, '');
|
|
+ strictEqual(stdout, '');
|
|
+ strictEqual(code, 0);
|
|
+ });
|
|
+
|
|
+ it('should properly escape import names as well', async () => {
|
|
+ const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
|
+ '--no-warnings',
|
|
+ '--experimental-wasm-modules',
|
|
+ '--input-type=module',
|
|
+ '--eval',
|
|
+ [
|
|
+ 'import { strictEqual } from "node:assert";',
|
|
+ `import * as wasmExports from ${JSON.stringify(fixtures.fileURL('es-modules/import-name.wasm'))};`,
|
|
+ 'assert.strictEqual(wasmExports.xor(), 12345);',
|
|
+ ].join('\n'),
|
|
+ ]);
|
|
+
|
|
+ strictEqual(stderr, '');
|
|
+ strictEqual(stdout, '');
|
|
+ strictEqual(code, 0);
|
|
+ });
|
|
+
|
|
it('should emit experimental warning', async () => {
|
|
const { code, signal, stderr } = await spawnPromisified(execPath, [
|
|
'--experimental-wasm-modules',
|
|
Index: node-v16.20.2/test/fixtures/es-modules/export-name-code-injection.wat
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ node-v16.20.2/test/fixtures/es-modules/export-name-code-injection.wat
|
|
@@ -0,0 +1,8 @@
|
|
+;; Compiled using the WebAssembly Binary Toolkit (https://github.com/WebAssembly/wabt)
|
|
+;; $ wat2wasm export-name-code-injection.wat
|
|
+
|
|
+(module
|
|
+ (global $0 i32 (i32.const 123))
|
|
+ (global $1 i32 (i32.const 456))
|
|
+ (export ";import.meta.done=()=>{};console.log('code injection');{/*" (global $0))
|
|
+ (export "/*/$;`//" (global $1)))
|
|
Index: node-v16.20.2/test/fixtures/es-modules/export-name-syntax-error.wat
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ node-v16.20.2/test/fixtures/es-modules/export-name-syntax-error.wat
|
|
@@ -0,0 +1,6 @@
|
|
+;; Compiled using the WebAssembly Binary Toolkit (https://github.com/WebAssembly/wabt)
|
|
+;; $ wat2wasm export-name-syntax-error.wat
|
|
+
|
|
+(module
|
|
+ (global $0 i32 (i32.const 12682))
|
|
+ (export "?f!o:o<b>a[r]" (global $0)))
|
|
Index: node-v16.20.2/test/fixtures/es-modules/import-name.wat
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ node-v16.20.2/test/fixtures/es-modules/import-name.wat
|
|
@@ -0,0 +1,10 @@
|
|
+;; Compiled using the WebAssembly Binary Toolkit (https://github.com/WebAssembly/wabt)
|
|
+;; $ wat2wasm import-name.wat
|
|
+
|
|
+(module
|
|
+ (global $0 (import "./export-name-code-injection.wasm" ";import.meta.done=()=>{};console.log('code injection');{/*") i32)
|
|
+ (global $1 (import "./export-name-code-injection.wasm" "/*/$;`//") i32)
|
|
+ (global $2 (import "./export-name-syntax-error.wasm" "?f!o:o<b>a[r]") i32)
|
|
+ (func $xor (result i32)
|
|
+ (i32.xor (i32.xor (global.get $0) (global.get $1)) (global.get $2)))
|
|
+ (export "xor" (func $xor)))
|
|
Index: node-v16.20.2/lib/internal/bootstrap/loaders.js
|
|
===================================================================
|
|
--- node-v16.20.2.orig/lib/internal/bootstrap/loaders.js
|
|
+++ node-v16.20.2/lib/internal/bootstrap/loaders.js
|
|
@@ -58,6 +58,7 @@ const {
|
|
SafeSet,
|
|
String,
|
|
StringPrototypeStartsWith,
|
|
+ StringPrototypeSlice,
|
|
TypeError,
|
|
} = primordials;
|
|
|
|
@@ -365,7 +366,9 @@ function nativeModuleRequire(id) {
|
|
// Allow internal modules from dependencies to require
|
|
// other modules from dependencies by providing fallbacks.
|
|
function requireWithFallbackInDeps(request) {
|
|
- if (!BuiltinModule.map.has(request)) {
|
|
+ if (StringPrototypeStartsWith(request, 'node:')) {
|
|
+ request = StringPrototypeSlice(request, 5);
|
|
+ } else if (!BuiltinModule.map.has(request)) {
|
|
request = `internal/deps/${request}`;
|
|
}
|
|
return nativeModuleRequire(request);
|