import assert from "node:assert/strict"; import crypto from "node:crypto"; import fs from "node:fs"; import path from "node:path"; import { spawnSync } from "node:child_process"; import { fileURLToPath } from "node:url"; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const reportPath = path.join(root, "tests/golden/M13-05F/malicious-input-report.json"); const manifestPath = path.join(root, "tests/golden/M13-05F/manifest.json"); const sha256 = (bytes) => crypto.createHash("sha256").update(bytes).digest("hex"); const fileSha256 = (file) => sha256(fs.readFileSync(file)); const commands = [ { id: "blend", command: process.execPath, args: ["tools/web/check-malicious-blends.mjs"], expected: "REJECTED" }, { id: "archive", command: process.execPath, args: ["tools/web/check-malicious-archive-fixtures.mjs"], expected: "REJECTED" }, { id: "image-font-media-node-manifest", command: process.execPath, args: ["--test", "web/tests/unit/asset-preview-decode.test.mjs", "web/tests/unit/external-vfont.test.mjs", "web/tests/unit/sequencer-media-cache.test.mjs", "web/tests/unit/shader-compiler.test.mjs", "web/tests/unit/script-manifest-budgets.test.mjs"], expected: "REJECTED" }, { id: "glb", command: process.execPath, args: ["--test", "web/tests/unit/glb-negative-cases.test.mjs"], expected: "REJECTED" }, ]; const results = commands.map((entry) => { const run = spawnSync(entry.command, entry.args, { cwd: root, encoding: "utf8", maxBuffer: 16 * 1024 * 1024 }); assert.equal(run.status, 0, `${entry.id} failed\n${run.stdout}\n${run.stderr}`); return { id: entry.id, status: entry.expected, exitCode: run.status }; }); const report = { schemaVersion: 1, task: "M13-05F", operation: "MALICIOUS_INPUT_MATRIX", cases: { blend: { status: "REJECTED", checker: "tools/web/check-malicious-blends.mjs", stableCode: "BLEND_OPEN_INVALID" }, image: { status: "REJECTED", checker: "web/tests/unit/asset-preview-decode.test.mjs", stableCodes: ["ASSET_MANIFEST_INVALID", "ASSET_BUDGET_EXCEEDED", "ASSET_SOURCE_HASH_MISMATCH"] }, font: { status: "REJECTED", checker: "web/tests/unit/external-vfont.test.mjs", stableCodes: ["NON_MESH_BINARY_INVALID", "NON_MESH_RESOURCE_OUTSIDE_PROJECT", "ASSET_SOURCE_HASH_MISMATCH"] }, media: { status: "REJECTED", checker: "web/tests/unit/sequencer-media-cache.test.mjs", stableCode: "SEQUENCER_SCHEMA_INVALID" }, archive: { status: "REJECTED", checker: "tools/web/check-malicious-archive-fixtures.mjs", stableCode: "IO_ARCHIVE_UNSAFE" }, nodeGraph: { status: "REJECTED", checker: "web/tests/unit/shader-compiler.test.mjs", stableCodes: ["SHADER_NODE_UNSUPPORTED", "SHADER_INVALID_GRAPH"] }, manifest: { status: "REJECTED", checker: "web/tests/unit/script-manifest-budgets.test.mjs", stableCode: "SCRIPT_MANIFEST_INVALID" }, glb: { status: "REJECTED", checker: "web/tests/unit/glb-negative-cases.test.mjs", stableCodes: ["GLB_SPARSE_ACCESSOR_UNSUPPORTED", "GLB_EXTENSION_UNSUPPORTED", "GLB_EXTERNAL_URI_BLOCKED", "GLB_IMPORT_BUDGET_EXCEEDED"] }, }, executions: results, allRejected: results.every((result) => result.status === "REJECTED"), execution: "DISABLED", nextTask: "M13-05G", }; if (process.env.UPDATE_M13_05F_REPORT === "1") { fs.mkdirSync(path.dirname(reportPath), { recursive: true }); fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); } assert.deepEqual(JSON.parse(fs.readFileSync(reportPath, "utf8")), report); const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8")); assert.deepEqual({ schemaVersion: manifest.schemaVersion, task: manifest.task, parentTask: manifest.parentTask, nextTask: manifest.nextTask }, { schemaVersion: 1, task: "M13-05F", parentTask: "M13-05E", nextTask: "M13-05G" }); for (const artifact of Object.values(manifest.artifacts)) assert.equal(fileSha256(path.join(root, artifact.path)), artifact.sha256, artifact.path); process.stdout.write("malicious-input-matrix-ok blend=REJECTED image=REJECTED font=REJECTED media=REJECTED archive=REJECTED nodeGraph=REJECTED manifest=REJECTED glb=REJECTED execution=DISABLED next=M13-05G\n");