From 5891c922840b46c13cf6f774c8d8789d7fb65d9c Mon Sep 17 00:00:00 2001 From: orbisai0security Date: Tue, 2 Jun 2026 00:24:57 +0000 Subject: [PATCH] fix: the wasm loader fetches shadertest in start.js The WASM loader fetches ShaderTest --- backends/system/wasm/js-sources/start.js | 7 ++- tests/invariant_start.test.js | 58 ++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tests/invariant_start.test.js diff --git a/backends/system/wasm/js-sources/start.js b/backends/system/wasm/js-sources/start.js index 1ea61de83..c7ea7d243 100644 --- a/backends/system/wasm/js-sources/start.js +++ b/backends/system/wasm/js-sources/start.js @@ -48,7 +48,12 @@ function write_string(ptr, str) { async function init() { let wasm_bytes = null; - await fetch("./ShaderTest.wasm").then(res => res.arrayBuffer()).then(buffer => wasm_bytes = new Uint8Array(buffer)); + await fetch("./ShaderTest.wasm").then(res => res.arrayBuffer()).then(buffer => { + wasm_bytes = new Uint8Array(buffer); + if (wasm_bytes[0] !== 0x00 || wasm_bytes[1] !== 0x61 || wasm_bytes[2] !== 0x73 || wasm_bytes[3] !== 0x6D) { + throw new Error("Invalid WASM binary: magic bytes verification failed"); + } + }); // Read memory size from wasm file let memory_size = 0; diff --git a/tests/invariant_start.test.js b/tests/invariant_start.test.js new file mode 100644 index 000000000..5ef58a8e4 --- /dev/null +++ b/tests/invariant_start.test.js @@ -0,0 +1,58 @@ +const fs = require('fs'); +const path = require('path'); + +describe("WASM loader should implement integrity verification for fetched resources", () => { + const startJsPath = path.join(__dirname, 'backends/system/wasm/js-sources/start.js'); + + // Test payloads representing different attack scenarios on the fetch URL + const payloads = [ + { url: "./ShaderTest.wasm", description: "original unverified fetch" }, + { url: "../../../malicious.wasm", description: "path traversal attack" }, + { url: "https://evil.com/ShaderTest.wasm", description: "external domain injection" }, + ]; + + test("source code must include integrity verification for WASM fetch", () => { + const sourceCode = fs.readFileSync(startJsPath, 'utf8'); + + // Security property: WASM fetches MUST have integrity verification + const hasIntegrityCheck = + sourceCode.includes('integrity') || + sourceCode.includes('SRI') || + sourceCode.includes('sha256') || + sourceCode.includes('sha384') || + sourceCode.includes('sha512') || + sourceCode.includes('verify') || + sourceCode.includes('checksum'); + + const hasCSPRestriction = + sourceCode.includes('Content-Security-Policy') || + sourceCode.includes('script-src') || + sourceCode.includes('wasm-unsafe-eval'); + + const hasSignatureVerification = + sourceCode.includes('signature') || + sourceCode.includes('crypto.subtle'); + + const hasAnyProtection = hasIntegrityCheck || hasCSPRestriction || hasSignatureVerification; + + expect(hasAnyProtection).toBe(true); + }); + + test.each(payloads)("fetch of $description should be protected", ({ url }) => { + const sourceCode = fs.readFileSync(startJsPath, 'utf8'); + + // If the URL pattern exists in code, it must be accompanied by integrity checks + if (sourceCode.includes(url) || sourceCode.includes('fetch(')) { + const fetchPattern = /fetch\s*\([^)]+\)/g; + const fetches = sourceCode.match(fetchPattern) || []; + + fetches.forEach(fetchCall => { + // Security invariant: fetch calls for WASM should not be bare/unverified + const isBareWasmFetch = fetchCall.includes('.wasm') && + !sourceCode.includes('integrity'); + + expect(isBareWasmFetch).toBe(false); + }); + } + }); +}); \ No newline at end of file