From dc83034a0352603a9e564b1124ce8d8f83cfc638 Mon Sep 17 00:00:00 2001 From: Felix Date: Sat, 15 Aug 2026 17:29:16 +0800 Subject: [PATCH 1/6] Add one-time JS runner rejection test updater --- .../one-time-js-runner-rejection-test.yml | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 .github/workflows/one-time-js-runner-rejection-test.yml diff --git a/.github/workflows/one-time-js-runner-rejection-test.yml b/.github/workflows/one-time-js-runner-rejection-test.yml new file mode 100644 index 0000000..cc3bec2 --- /dev/null +++ b/.github/workflows/one-time-js-runner-rejection-test.yml @@ -0,0 +1,103 @@ +name: One-time JS runner rejection test updater + +on: + push: + branches: [test/exercise-js-runner-rejections] + +permissions: + contents: write + +jobs: + update: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-node@v7 + with: + node-version: 24 + cache: npm + - run: npm ci + - name: Make adversarial runner cases actually exercise parser + shell: bash + run: | + python3 <<'PY' + from pathlib import Path + + path = Path('tests/js-runners.test.ts') + text = path.read_text() + old = '''test("shell-like prefixes, command chains, unsupported wrappers, and excessive environment prefixes stay opaque", async (context) => { + const root = await initializeRepository({ + "package.json": JSON.stringify({ scripts: { + test: "jest --coverage", + "test:substitution": "FOO=$(command) jest", + "test:chain": "NODE_ENV=test jest && eslint .", + "test:dotenv": "dotenv -e .env -- vitest run", + "test:concurrently": "concurrently jest vitest", + "test:cross-env-shell": "cross-env-shell NODE_ENV=test jest", + "test:too-many-env": "A=1 B=2 C=3 D=4 E=5 jest", + "test:duplicate-env": "CI=1 CI=true jest", + } }), + "test/value.test.js": "export const value = true;\\n", + "node_modules/jest/package.json": JSON.stringify({ bin: { jest: "./bin/jest.cjs" } }), + "node_modules/jest/bin/jest.cjs": JEST_BIN, + "node_modules/vitest/package.json": JSON.stringify({ bin: { vitest: "./vitest.cjs" } }), + "node_modules/vitest/vitest.cjs": VITEST_BIN, + "node_modules/cross-env/package.json": JSON.stringify({ name: "cross-env", version: "1.0.0" }), + }); + context.after(() => rm(root, { recursive: true, force: true })); + + const discovery = await discoverChecks(root); + const targeted = await targetedJsFrameworkChecks(root, discovery.checks, ["test/value.test.js"]); + assert.deepEqual(targeted.checks, []); +}); +''' + new = '''test("unsafe Jest and Vitest script shapes are individually exercised and stay opaque", async (context) => { + const cases = [ + { label: "unsupported Jest flag", script: "jest --coverage" }, + { label: "command substitution", script: "FOO=$(command) jest" }, + { label: "command chain", script: "NODE_ENV=test jest && eslint ." }, + { label: "dotenv wrapper", script: "dotenv -e .env -- vitest run" }, + { label: "concurrently wrapper", script: "concurrently jest vitest" }, + { label: "cross-env-shell wrapper", script: "cross-env-shell NODE_ENV=test jest" }, + { label: "too many environment assignments", script: "A=1 B=2 C=3 D=4 E=5 jest" }, + { label: "duplicate environment assignment", script: "CI=1 CI=true jest" }, + { label: "non-ASCII whitespace", script: "jest\\u00a0--ci" }, + ]; + + for (const { label, script } of cases) { + const root = await initializeRepository({ + "package.json": JSON.stringify({ scripts: { test: script } }), + "test/value.test.js": "export const value = true;\\n", + "node_modules/jest/package.json": JSON.stringify({ bin: { jest: "./bin/jest.cjs" } }), + "node_modules/jest/bin/jest.cjs": JEST_BIN, + "node_modules/vitest/package.json": JSON.stringify({ bin: { vitest: "./vitest.cjs" } }), + "node_modules/vitest/vitest.cjs": VITEST_BIN, + "node_modules/cross-env/package.json": JSON.stringify({ name: "cross-env", version: "1.0.0" }), + }); + context.after(() => rm(root, { recursive: true, force: true })); + + const discovery = await discoverChecks(root); + const discoveredJsTests = discovery.checks.filter((check) => check.id.startsWith("js:test:")); + assert.equal(discoveredJsTests.length, 1, `${label}: adversarial script must be discovered as a test check`); + assert.equal(discoveredJsTests[0]?.id, "js:test:test", `${label}: parser must receive the recognized test script`); + + const targeted = await targetedJsFrameworkChecks(root, discovery.checks, ["test/value.test.js"]); + assert.deepEqual(targeted.checks, [], `${label}: unsafe command shape must remain opaque`); + } +}); +''' + if text.count(old) != 1: + raise RuntimeError(f'expected adversarial test block exactly once, found {text.count(old)}') + path.write_text(text.replace(old, new, 1)) + PY + - run: npm test + - name: Commit test correction + shell: bash + run: | + git config user.name github-actions[bot] + git config user.email 41898282+github-actions[bot]@users.noreply.github.com + git add tests/js-runners.test.ts + git diff --cached --check + git commit -m "Exercise adversarial JS runner parser cases" + git push From b68a5e79534dd7f710dce13acea76e71f7ed4629 Mon Sep 17 00:00:00 2001 From: Felix Date: Sat, 15 Aug 2026 17:30:42 +0800 Subject: [PATCH 2/6] Fix one-time JS runner rejection test updater --- .../one-time-js-runner-rejection-test.yml | 65 +------------------ 1 file changed, 3 insertions(+), 62 deletions(-) diff --git a/.github/workflows/one-time-js-runner-rejection-test.yml b/.github/workflows/one-time-js-runner-rejection-test.yml index cc3bec2..cd546a4 100644 --- a/.github/workflows/one-time-js-runner-rejection-test.yml +++ b/.github/workflows/one-time-js-runner-rejection-test.yml @@ -22,71 +22,12 @@ jobs: shell: bash run: | python3 <<'PY' + from base64 import b64decode from pathlib import Path - + old = b64decode('dGVzdCgic2hlbGwtbGlrZSBwcmVmaXhlcywgY29tbWFuZCBjaGFpbnMsIHVuc3VwcG9ydGVkIHdyYXBwZXJzLCBhbmQgZXhjZXNzaXZlIGVudmlyb25tZW50IHByZWZpeGVzIHN0YXkgb3BhcXVlIiwgYXN5bmMgKGNvbnRleHQpID0+IHsKICBjb25zdCByb290ID0gYXdhaXQgaW5pdGlhbGl6ZVJlcG9zaXRvcnkoewogICAgInBhY2thZ2UuanNvbiI6IEpTT04uc3RyaW5naWZ5KHsgc2NyaXB0czogewogICAgICB0ZXN0OiAiamVzdCAtLWNvdmVyYWdlIiwKICAgICAgInRlc3Q6c3Vic3RpdHV0aW9uIjogIkZPTz0kKGNvbW1hbmQpIGplc3QiLAogICAgICAidGVzdDpjaGFpbiI6ICJOT0RFX0VOVj10ZXN0IGplc3QgJiYgZXNsaW50IC4iLAogICAgICAidGVzdDpkb3RlbnYiOiAiZG90ZW52IC1lIC5lbnYgLS0gdml0ZXN0IHJ1biIsCiAgICAgICJ0ZXN0OmNvbmN1cnJlbnRseSI6ICJjb25jdXJyZW50bHkgamVzdCB2aXRlc3QiLAogICAgICAidGVzdDpjcm9zcy1lbnYtc2hlbGwiOiAiY3Jvc3MtZW52LXNoZWxsIE5PREVfRU5WPXRlc3QgamVzdCIsCiAgICAgICJ0ZXN0OnRvby1tYW55LWVudiI6ICJBPTEgQj0yIEM9MyBEPTQgRT01IGplc3QiLAogICAgICAidGVzdDpkdXBsaWNhdGUtZW52IjogIkNJPTEgQ0k9dHJ1ZSBqZXN0IiwKICAgIH0gfSksCiAgICAidGVzdC92YWx1ZS50ZXN0LmpzIjogImV4cG9ydCBjb25zdCB2YWx1ZSA9IHRydWU7XG4iLAogICAgIm5vZGVfbW9kdWxlcy9qZXN0L3BhY2thZ2UuanNvbiI6IEpTT04uc3RyaW5naWZ5KHsgYmluOiB7IGplc3Q6ICIuL2Jpbi9qZXN0LmNqcyIgfSB9KSwKICAgICJub2RlX21vZHVsZXMvamVzdC9iaW4vamVzdC5janMiOiBKRVNUX0JJTiwKICAgICJub2RlX21vZHVsZXMvdml0ZXN0L3BhY2thZ2UuanNvbiI6IEpTT04uc3RyaW5naWZ5KHsgYmluOiB7IHZpdGVzdDogIi4vdml0ZXN0LmNqcyIgfSB9KSwKICAgICJub2RlX21vZHVsZXMvdml0ZXN0L3ZpdGVzdC5janMiOiBWSVRFU1RfQklOLAogICAgIm5vZGVfbW9kdWxlcy9jcm9zcy1lbnYvcGFja2FnZS5qc29uIjogSlNPTi5zdHJpbmdpZnkoeyBuYW1lOiAiY3Jvc3MtZW52IiwgdmVyc2lvbjogIjEuMC4wIiB9KSwKICB9KTsKICBjb250ZXh0LmFmdGVyKCgpID0+IHJtKHJvb3QsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KSk7CgogIGNvbnN0IGRpc2NvdmVyeSA9IGF3YWl0IGRpc2NvdmVyQ2hlY2tzKHJvb3QpOwogIGNvbnN0IHRhcmdldGVkID0gYXdhaXQgdGFyZ2V0ZWRKc0ZyYW1ld29ya0NoZWNrcyhyb290LCBkaXNjb3ZlcnkuY2hlY2tzLCBbInRlc3QvdmFsdWUudGVzdC5qcyJdKTsKICBhc3NlcnQuZGVlcEVxdWFsKHRhcmdldGVkLmNoZWNrcywgW10pOwp9KTsK').decode() + new = b64decode('dGVzdCgidW5zYWZlIEplc3QgYW5kIFZpdGVzdCBzY3JpcHQgc2hhcGVzIGFyZSBpbmRpdmlkdWFsbHkgZXhlcmNpc2VkIGFuZCBzdGF5IG9wYXF1ZSIsIGFzeW5jIChjb250ZXh0KSA9PiB7CiAgY29uc3QgY2FzZXMgPSBbCiAgICB7IGxhYmVsOiAidW5zdXBwb3J0ZWQgSmVzdCBmbGFnIiwgc2NyaXB0OiAiamVzdCAtLWNvdmVyYWdlIiB9LAogICAgeyBsYWJlbDogImNvbW1hbmQgc3Vic3RpdHV0aW9uIiwgc2NyaXB0OiAiRk9PPSQoY29tbWFuZCkgamVzdCIgfSwKICAgIHsgbGFiZWw6ICJjb21tYW5kIGNoYWluIiwgc2NyaXB0OiAiTk9ERV9FTlY9dGVzdCBqZXN0ICYmIGVzbGludCAuIiB9LAogICAgeyBsYWJlbDogImRvdGVudiB3cmFwcGVyIiwgc2NyaXB0OiAiZG90ZW52IC1lIC5lbnYgLS0gdml0ZXN0IHJ1biIgfSwKICAgIHsgbGFiZWw6ICJjb25jdXJyZW50bHkgd3JhcHBlciIsIHNjcmlwdDogImNvbmN1cnJlbnRseSBqZXN0IHZpdGVzdCIgfSwKICAgIHsgbGFiZWw6ICJjcm9zcy1lbnYtc2hlbGwgd3JhcHBlciIsIHNjcmlwdDogImNyb3NzLWVudi1zaGVsbCBOT0RFX0VOVj10ZXN0IGplc3QiIH0sCiAgICB7IGxhYmVsOiAidG9vIG1hbnkgZW52aXJvbm1lbnQgYXNzaWdubWVudHMiLCBzY3JpcHQ6ICJBPTEgQj0yIEM9MyBEPTQgRT01IGplc3QiIH0sCiAgICB7IGxhYmVsOiAiZHVwbGljYXRlIGVudmlyb25tZW50IGFzc2lnbm1lbnQiLCBzY3JpcHQ6ICJDST0xIENJPXRydWUgamVzdCIgfSwKICAgIHsgbGFiZWw6ICJub24tQVNDSUkgd2hpdGVzcGFjZSIsIHNjcmlwdDogImplc3RcdTAwYTAtLWNpIiB9LAogIF07CgogIGZvciAoY29uc3QgeyBsYWJlbCwgc2NyaXB0IH0gb2YgY2FzZXMpIHsKICAgIGNvbnN0IHJvb3QgPSBhd2FpdCBpbml0aWFsaXplUmVwb3NpdG9yeSh7CiAgICAgICJwYWNrYWdlLmpzb24iOiBKU09OLnN0cmluZ2lmeSh7IHNjcmlwdHM6IHsgdGVzdDogc2NyaXB0IH0gfSksCiAgICAgICJ0ZXN0L3ZhbHVlLnRlc3QuanMiOiAiZXhwb3J0IGNvbnN0IHZhbHVlID0gdHJ1ZTtcbiIsCiAgICAgICJub2RlX21vZHVsZXMvamVzdC9wYWNrYWdlLmpzb24iOiBKU09OLnN0cmluZ2lmeSh7IGJpbjogeyBqZXN0OiAiLi9iaW4vamVzdC5janMiIH0gfSksCiAgICAgICJub2RlX21vZHVsZXMvamVzdC9iaW4vamVzdC5janMiOiBKRVNUX0JJTiwKICAgICAgIm5vZGVfbW9kdWxlcy92aXRlc3QvcGFja2FnZS5qc29uIjogSlNPTi5zdHJpbmdpZnkoeyBiaW46IHsgdml0ZXN0OiAiLi92aXRlc3QuY2pzIiB9IH0pLAogICAgICAibm9kZV9tb2R1bGVzL3ZpdGVzdC92aXRlc3QuY2pzIjogVklURVNUX0JJTiwKICAgICAgIm5vZGVfbW9kdWxlcy9jcm9zcy1lbnYvcGFja2FnZS5qc29uIjogSlNPTi5zdHJpbmdpZnkoeyBuYW1lOiAiY3Jvc3MtZW52IiwgdmVyc2lvbjogIjEuMC4wIiB9KSwKICAgIH0pOwogICAgY29udGV4dC5hZnRlcigoKSA9PiBybShyb290LCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSkpOwoKICAgIGNvbnN0IGRpc2NvdmVyeSA9IGF3YWl0IGRpc2NvdmVyQ2hlY2tzKHJvb3QpOwogICAgY29uc3QgZGlzY292ZXJlZEpzVGVzdHMgPSBkaXNjb3ZlcnkuY2hlY2tzLmZpbHRlcigoY2hlY2spID0+IGNoZWNrLmlkLnN0YXJ0c1dpdGgoImpzOnRlc3Q6IikpOwogICAgYXNzZXJ0LmVxdWFsKGRpc2NvdmVyZWRKc1Rlc3RzLmxlbmd0aCwgMSwgYCR7bGFiZWx9OiBhZHZlcnNhcmlhbCBzY3JpcHQgbXVzdCBiZSBkaXNjb3ZlcmVkIGFzIGEgdGVzdCBjaGVja2ApOwogICAgYXNzZXJ0LmVxdWFsKGRpc2NvdmVyZWRKc1Rlc3RzWzBdPy5pZCwgImpzOnRlc3Q6dGVzdCIsIGAke2xhYmVsfTogcGFyc2VyIG11c3QgcmVjZWl2ZSB0aGUgcmVjb2duaXplZCB0ZXN0IHNjcmlwdGApOwoKICAgIGNvbnN0IHRhcmdldGVkID0gYXdhaXQgdGFyZ2V0ZWRKc0ZyYW1ld29ya0NoZWNrcyhyb290LCBkaXNjb3ZlcnkuY2hlY2tzLCBbInRlc3QvdmFsdWUudGVzdC5qcyJdKTsKICAgIGFzc2VydC5kZWVwRXF1YWwodGFyZ2V0ZWQuY2hlY2tzLCBbXSwgYCR7bGFiZWx9OiB1bnNhZmUgY29tbWFuZCBzaGFwZSBtdXN0IHJlbWFpbiBvcGFxdWVgKTsKICB9Cn0pOwo=').decode() path = Path('tests/js-runners.test.ts') text = path.read_text() - old = '''test("shell-like prefixes, command chains, unsupported wrappers, and excessive environment prefixes stay opaque", async (context) => { - const root = await initializeRepository({ - "package.json": JSON.stringify({ scripts: { - test: "jest --coverage", - "test:substitution": "FOO=$(command) jest", - "test:chain": "NODE_ENV=test jest && eslint .", - "test:dotenv": "dotenv -e .env -- vitest run", - "test:concurrently": "concurrently jest vitest", - "test:cross-env-shell": "cross-env-shell NODE_ENV=test jest", - "test:too-many-env": "A=1 B=2 C=3 D=4 E=5 jest", - "test:duplicate-env": "CI=1 CI=true jest", - } }), - "test/value.test.js": "export const value = true;\\n", - "node_modules/jest/package.json": JSON.stringify({ bin: { jest: "./bin/jest.cjs" } }), - "node_modules/jest/bin/jest.cjs": JEST_BIN, - "node_modules/vitest/package.json": JSON.stringify({ bin: { vitest: "./vitest.cjs" } }), - "node_modules/vitest/vitest.cjs": VITEST_BIN, - "node_modules/cross-env/package.json": JSON.stringify({ name: "cross-env", version: "1.0.0" }), - }); - context.after(() => rm(root, { recursive: true, force: true })); - - const discovery = await discoverChecks(root); - const targeted = await targetedJsFrameworkChecks(root, discovery.checks, ["test/value.test.js"]); - assert.deepEqual(targeted.checks, []); -}); -''' - new = '''test("unsafe Jest and Vitest script shapes are individually exercised and stay opaque", async (context) => { - const cases = [ - { label: "unsupported Jest flag", script: "jest --coverage" }, - { label: "command substitution", script: "FOO=$(command) jest" }, - { label: "command chain", script: "NODE_ENV=test jest && eslint ." }, - { label: "dotenv wrapper", script: "dotenv -e .env -- vitest run" }, - { label: "concurrently wrapper", script: "concurrently jest vitest" }, - { label: "cross-env-shell wrapper", script: "cross-env-shell NODE_ENV=test jest" }, - { label: "too many environment assignments", script: "A=1 B=2 C=3 D=4 E=5 jest" }, - { label: "duplicate environment assignment", script: "CI=1 CI=true jest" }, - { label: "non-ASCII whitespace", script: "jest\\u00a0--ci" }, - ]; - - for (const { label, script } of cases) { - const root = await initializeRepository({ - "package.json": JSON.stringify({ scripts: { test: script } }), - "test/value.test.js": "export const value = true;\\n", - "node_modules/jest/package.json": JSON.stringify({ bin: { jest: "./bin/jest.cjs" } }), - "node_modules/jest/bin/jest.cjs": JEST_BIN, - "node_modules/vitest/package.json": JSON.stringify({ bin: { vitest: "./vitest.cjs" } }), - "node_modules/vitest/vitest.cjs": VITEST_BIN, - "node_modules/cross-env/package.json": JSON.stringify({ name: "cross-env", version: "1.0.0" }), - }); - context.after(() => rm(root, { recursive: true, force: true })); - - const discovery = await discoverChecks(root); - const discoveredJsTests = discovery.checks.filter((check) => check.id.startsWith("js:test:")); - assert.equal(discoveredJsTests.length, 1, `${label}: adversarial script must be discovered as a test check`); - assert.equal(discoveredJsTests[0]?.id, "js:test:test", `${label}: parser must receive the recognized test script`); - - const targeted = await targetedJsFrameworkChecks(root, discovery.checks, ["test/value.test.js"]); - assert.deepEqual(targeted.checks, [], `${label}: unsafe command shape must remain opaque`); - } -}); -''' if text.count(old) != 1: raise RuntimeError(f'expected adversarial test block exactly once, found {text.count(old)}') path.write_text(text.replace(old, new, 1)) From 0867c1fea3e098c72df45e8abf02307e1280ea99 Mon Sep 17 00:00:00 2001 From: Felix Date: Sat, 15 Aug 2026 17:30:54 +0800 Subject: [PATCH 3/6] Trigger corrected JS runner test updater --- .one-time-js-runner-trigger | 1 + 1 file changed, 1 insertion(+) create mode 100644 .one-time-js-runner-trigger diff --git a/.one-time-js-runner-trigger b/.one-time-js-runner-trigger new file mode 100644 index 0000000..5c33b15 --- /dev/null +++ b/.one-time-js-runner-trigger @@ -0,0 +1 @@ +trigger From 74d58cadcabcef6e28e0eec4edf7e2b9f64702a4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 15 Aug 2026 09:31:35 +0000 Subject: [PATCH 4/6] Exercise adversarial JS runner parser cases --- tests/js-runners.test.ts | 57 +++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/tests/js-runners.test.ts b/tests/js-runners.test.ts index f6ce954..e7347a4 100644 --- a/tests/js-runners.test.ts +++ b/tests/js-runners.test.ts @@ -201,30 +201,39 @@ test("custom Jest or Vitest command shapes stay opaque instead of inventing targ assert.deepEqual(targeted.checks, []); }); -test("shell-like prefixes, command chains, unsupported wrappers, and excessive environment prefixes stay opaque", async (context) => { - const root = await initializeRepository({ - "package.json": JSON.stringify({ scripts: { - test: "jest --coverage", - "test:substitution": "FOO=$(command) jest", - "test:chain": "NODE_ENV=test jest && eslint .", - "test:dotenv": "dotenv -e .env -- vitest run", - "test:concurrently": "concurrently jest vitest", - "test:cross-env-shell": "cross-env-shell NODE_ENV=test jest", - "test:too-many-env": "A=1 B=2 C=3 D=4 E=5 jest", - "test:duplicate-env": "CI=1 CI=true jest", - } }), - "test/value.test.js": "export const value = true;\n", - "node_modules/jest/package.json": JSON.stringify({ bin: { jest: "./bin/jest.cjs" } }), - "node_modules/jest/bin/jest.cjs": JEST_BIN, - "node_modules/vitest/package.json": JSON.stringify({ bin: { vitest: "./vitest.cjs" } }), - "node_modules/vitest/vitest.cjs": VITEST_BIN, - "node_modules/cross-env/package.json": JSON.stringify({ name: "cross-env", version: "1.0.0" }), - }); - context.after(() => rm(root, { recursive: true, force: true })); - - const discovery = await discoverChecks(root); - const targeted = await targetedJsFrameworkChecks(root, discovery.checks, ["test/value.test.js"]); - assert.deepEqual(targeted.checks, []); +test("unsafe Jest and Vitest script shapes are individually exercised and stay opaque", async (context) => { + const cases = [ + { label: "unsupported Jest flag", script: "jest --coverage" }, + { label: "command substitution", script: "FOO=$(command) jest" }, + { label: "command chain", script: "NODE_ENV=test jest && eslint ." }, + { label: "dotenv wrapper", script: "dotenv -e .env -- vitest run" }, + { label: "concurrently wrapper", script: "concurrently jest vitest" }, + { label: "cross-env-shell wrapper", script: "cross-env-shell NODE_ENV=test jest" }, + { label: "too many environment assignments", script: "A=1 B=2 C=3 D=4 E=5 jest" }, + { label: "duplicate environment assignment", script: "CI=1 CI=true jest" }, + { label: "non-ASCII whitespace", script: "jest\u00a0--ci" }, + ]; + + for (const { label, script } of cases) { + const root = await initializeRepository({ + "package.json": JSON.stringify({ scripts: { test: script } }), + "test/value.test.js": "export const value = true;\n", + "node_modules/jest/package.json": JSON.stringify({ bin: { jest: "./bin/jest.cjs" } }), + "node_modules/jest/bin/jest.cjs": JEST_BIN, + "node_modules/vitest/package.json": JSON.stringify({ bin: { vitest: "./vitest.cjs" } }), + "node_modules/vitest/vitest.cjs": VITEST_BIN, + "node_modules/cross-env/package.json": JSON.stringify({ name: "cross-env", version: "1.0.0" }), + }); + context.after(() => rm(root, { recursive: true, force: true })); + + const discovery = await discoverChecks(root); + const discoveredJsTests = discovery.checks.filter((check) => check.id.startsWith("js:test:")); + assert.equal(discoveredJsTests.length, 1, `${label}: adversarial script must be discovered as a test check`); + assert.equal(discoveredJsTests[0]?.id, "js:test:test", `${label}: parser must receive the recognized test script`); + + const targeted = await targetedJsFrameworkChecks(root, discovery.checks, ["test/value.test.js"]); + assert.deepEqual(targeted.checks, [], `${label}: unsafe command shape must remain opaque`); + } }); test("a runner JSON report with no exact suite result cannot strengthen evidence", async (context) => { From 52c3596e1358357bfeb738ea3d6766500450a110 Mon Sep 17 00:00:00 2001 From: Felix Date: Sat, 15 Aug 2026 17:32:01 +0800 Subject: [PATCH 5/6] Remove one-time JS runner rejection test updater --- .../one-time-js-runner-rejection-test.yml | 44 ------------------- 1 file changed, 44 deletions(-) delete mode 100644 .github/workflows/one-time-js-runner-rejection-test.yml diff --git a/.github/workflows/one-time-js-runner-rejection-test.yml b/.github/workflows/one-time-js-runner-rejection-test.yml deleted file mode 100644 index cd546a4..0000000 --- a/.github/workflows/one-time-js-runner-rejection-test.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: One-time JS runner rejection test updater - -on: - push: - branches: [test/exercise-js-runner-rejections] - -permissions: - contents: write - -jobs: - update: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v7 - - uses: actions/setup-node@v7 - with: - node-version: 24 - cache: npm - - run: npm ci - - name: Make adversarial runner cases actually exercise parser - shell: bash - run: | - python3 <<'PY' - from base64 import b64decode - from pathlib import Path - old = b64decode('dGVzdCgic2hlbGwtbGlrZSBwcmVmaXhlcywgY29tbWFuZCBjaGFpbnMsIHVuc3VwcG9ydGVkIHdyYXBwZXJzLCBhbmQgZXhjZXNzaXZlIGVudmlyb25tZW50IHByZWZpeGVzIHN0YXkgb3BhcXVlIiwgYXN5bmMgKGNvbnRleHQpID0+IHsKICBjb25zdCByb290ID0gYXdhaXQgaW5pdGlhbGl6ZVJlcG9zaXRvcnkoewogICAgInBhY2thZ2UuanNvbiI6IEpTT04uc3RyaW5naWZ5KHsgc2NyaXB0czogewogICAgICB0ZXN0OiAiamVzdCAtLWNvdmVyYWdlIiwKICAgICAgInRlc3Q6c3Vic3RpdHV0aW9uIjogIkZPTz0kKGNvbW1hbmQpIGplc3QiLAogICAgICAidGVzdDpjaGFpbiI6ICJOT0RFX0VOVj10ZXN0IGplc3QgJiYgZXNsaW50IC4iLAogICAgICAidGVzdDpkb3RlbnYiOiAiZG90ZW52IC1lIC5lbnYgLS0gdml0ZXN0IHJ1biIsCiAgICAgICJ0ZXN0OmNvbmN1cnJlbnRseSI6ICJjb25jdXJyZW50bHkgamVzdCB2aXRlc3QiLAogICAgICAidGVzdDpjcm9zcy1lbnYtc2hlbGwiOiAiY3Jvc3MtZW52LXNoZWxsIE5PREVfRU5WPXRlc3QgamVzdCIsCiAgICAgICJ0ZXN0OnRvby1tYW55LWVudiI6ICJBPTEgQj0yIEM9MyBEPTQgRT01IGplc3QiLAogICAgICAidGVzdDpkdXBsaWNhdGUtZW52IjogIkNJPTEgQ0k9dHJ1ZSBqZXN0IiwKICAgIH0gfSksCiAgICAidGVzdC92YWx1ZS50ZXN0LmpzIjogImV4cG9ydCBjb25zdCB2YWx1ZSA9IHRydWU7XG4iLAogICAgIm5vZGVfbW9kdWxlcy9qZXN0L3BhY2thZ2UuanNvbiI6IEpTT04uc3RyaW5naWZ5KHsgYmluOiB7IGplc3Q6ICIuL2Jpbi9qZXN0LmNqcyIgfSB9KSwKICAgICJub2RlX21vZHVsZXMvamVzdC9iaW4vamVzdC5janMiOiBKRVNUX0JJTiwKICAgICJub2RlX21vZHVsZXMvdml0ZXN0L3BhY2thZ2UuanNvbiI6IEpTT04uc3RyaW5naWZ5KHsgYmluOiB7IHZpdGVzdDogIi4vdml0ZXN0LmNqcyIgfSB9KSwKICAgICJub2RlX21vZHVsZXMvdml0ZXN0L3ZpdGVzdC5janMiOiBWSVRFU1RfQklOLAogICAgIm5vZGVfbW9kdWxlcy9jcm9zcy1lbnYvcGFja2FnZS5qc29uIjogSlNPTi5zdHJpbmdpZnkoeyBuYW1lOiAiY3Jvc3MtZW52IiwgdmVyc2lvbjogIjEuMC4wIiB9KSwKICB9KTsKICBjb250ZXh0LmFmdGVyKCgpID0+IHJtKHJvb3QsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KSk7CgogIGNvbnN0IGRpc2NvdmVyeSA9IGF3YWl0IGRpc2NvdmVyQ2hlY2tzKHJvb3QpOwogIGNvbnN0IHRhcmdldGVkID0gYXdhaXQgdGFyZ2V0ZWRKc0ZyYW1ld29ya0NoZWNrcyhyb290LCBkaXNjb3ZlcnkuY2hlY2tzLCBbInRlc3QvdmFsdWUudGVzdC5qcyJdKTsKICBhc3NlcnQuZGVlcEVxdWFsKHRhcmdldGVkLmNoZWNrcywgW10pOwp9KTsK').decode() - new = b64decode('dGVzdCgidW5zYWZlIEplc3QgYW5kIFZpdGVzdCBzY3JpcHQgc2hhcGVzIGFyZSBpbmRpdmlkdWFsbHkgZXhlcmNpc2VkIGFuZCBzdGF5IG9wYXF1ZSIsIGFzeW5jIChjb250ZXh0KSA9PiB7CiAgY29uc3QgY2FzZXMgPSBbCiAgICB7IGxhYmVsOiAidW5zdXBwb3J0ZWQgSmVzdCBmbGFnIiwgc2NyaXB0OiAiamVzdCAtLWNvdmVyYWdlIiB9LAogICAgeyBsYWJlbDogImNvbW1hbmQgc3Vic3RpdHV0aW9uIiwgc2NyaXB0OiAiRk9PPSQoY29tbWFuZCkgamVzdCIgfSwKICAgIHsgbGFiZWw6ICJjb21tYW5kIGNoYWluIiwgc2NyaXB0OiAiTk9ERV9FTlY9dGVzdCBqZXN0ICYmIGVzbGludCAuIiB9LAogICAgeyBsYWJlbDogImRvdGVudiB3cmFwcGVyIiwgc2NyaXB0OiAiZG90ZW52IC1lIC5lbnYgLS0gdml0ZXN0IHJ1biIgfSwKICAgIHsgbGFiZWw6ICJjb25jdXJyZW50bHkgd3JhcHBlciIsIHNjcmlwdDogImNvbmN1cnJlbnRseSBqZXN0IHZpdGVzdCIgfSwKICAgIHsgbGFiZWw6ICJjcm9zcy1lbnYtc2hlbGwgd3JhcHBlciIsIHNjcmlwdDogImNyb3NzLWVudi1zaGVsbCBOT0RFX0VOVj10ZXN0IGplc3QiIH0sCiAgICB7IGxhYmVsOiAidG9vIG1hbnkgZW52aXJvbm1lbnQgYXNzaWdubWVudHMiLCBzY3JpcHQ6ICJBPTEgQj0yIEM9MyBEPTQgRT01IGplc3QiIH0sCiAgICB7IGxhYmVsOiAiZHVwbGljYXRlIGVudmlyb25tZW50IGFzc2lnbm1lbnQiLCBzY3JpcHQ6ICJDST0xIENJPXRydWUgamVzdCIgfSwKICAgIHsgbGFiZWw6ICJub24tQVNDSUkgd2hpdGVzcGFjZSIsIHNjcmlwdDogImplc3RcdTAwYTAtLWNpIiB9LAogIF07CgogIGZvciAoY29uc3QgeyBsYWJlbCwgc2NyaXB0IH0gb2YgY2FzZXMpIHsKICAgIGNvbnN0IHJvb3QgPSBhd2FpdCBpbml0aWFsaXplUmVwb3NpdG9yeSh7CiAgICAgICJwYWNrYWdlLmpzb24iOiBKU09OLnN0cmluZ2lmeSh7IHNjcmlwdHM6IHsgdGVzdDogc2NyaXB0IH0gfSksCiAgICAgICJ0ZXN0L3ZhbHVlLnRlc3QuanMiOiAiZXhwb3J0IGNvbnN0IHZhbHVlID0gdHJ1ZTtcbiIsCiAgICAgICJub2RlX21vZHVsZXMvamVzdC9wYWNrYWdlLmpzb24iOiBKU09OLnN0cmluZ2lmeSh7IGJpbjogeyBqZXN0OiAiLi9iaW4vamVzdC5janMiIH0gfSksCiAgICAgICJub2RlX21vZHVsZXMvamVzdC9iaW4vamVzdC5janMiOiBKRVNUX0JJTiwKICAgICAgIm5vZGVfbW9kdWxlcy92aXRlc3QvcGFja2FnZS5qc29uIjogSlNPTi5zdHJpbmdpZnkoeyBiaW46IHsgdml0ZXN0OiAiLi92aXRlc3QuY2pzIiB9IH0pLAogICAgICAibm9kZV9tb2R1bGVzL3ZpdGVzdC92aXRlc3QuY2pzIjogVklURVNUX0JJTiwKICAgICAgIm5vZGVfbW9kdWxlcy9jcm9zcy1lbnYvcGFja2FnZS5qc29uIjogSlNPTi5zdHJpbmdpZnkoeyBuYW1lOiAiY3Jvc3MtZW52IiwgdmVyc2lvbjogIjEuMC4wIiB9KSwKICAgIH0pOwogICAgY29udGV4dC5hZnRlcigoKSA9PiBybShyb290LCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSkpOwoKICAgIGNvbnN0IGRpc2NvdmVyeSA9IGF3YWl0IGRpc2NvdmVyQ2hlY2tzKHJvb3QpOwogICAgY29uc3QgZGlzY292ZXJlZEpzVGVzdHMgPSBkaXNjb3ZlcnkuY2hlY2tzLmZpbHRlcigoY2hlY2spID0+IGNoZWNrLmlkLnN0YXJ0c1dpdGgoImpzOnRlc3Q6IikpOwogICAgYXNzZXJ0LmVxdWFsKGRpc2NvdmVyZWRKc1Rlc3RzLmxlbmd0aCwgMSwgYCR7bGFiZWx9OiBhZHZlcnNhcmlhbCBzY3JpcHQgbXVzdCBiZSBkaXNjb3ZlcmVkIGFzIGEgdGVzdCBjaGVja2ApOwogICAgYXNzZXJ0LmVxdWFsKGRpc2NvdmVyZWRKc1Rlc3RzWzBdPy5pZCwgImpzOnRlc3Q6dGVzdCIsIGAke2xhYmVsfTogcGFyc2VyIG11c3QgcmVjZWl2ZSB0aGUgcmVjb2duaXplZCB0ZXN0IHNjcmlwdGApOwoKICAgIGNvbnN0IHRhcmdldGVkID0gYXdhaXQgdGFyZ2V0ZWRKc0ZyYW1ld29ya0NoZWNrcyhyb290LCBkaXNjb3ZlcnkuY2hlY2tzLCBbInRlc3QvdmFsdWUudGVzdC5qcyJdKTsKICAgIGFzc2VydC5kZWVwRXF1YWwodGFyZ2V0ZWQuY2hlY2tzLCBbXSwgYCR7bGFiZWx9OiB1bnNhZmUgY29tbWFuZCBzaGFwZSBtdXN0IHJlbWFpbiBvcGFxdWVgKTsKICB9Cn0pOwo=').decode() - path = Path('tests/js-runners.test.ts') - text = path.read_text() - if text.count(old) != 1: - raise RuntimeError(f'expected adversarial test block exactly once, found {text.count(old)}') - path.write_text(text.replace(old, new, 1)) - PY - - run: npm test - - name: Commit test correction - shell: bash - run: | - git config user.name github-actions[bot] - git config user.email 41898282+github-actions[bot]@users.noreply.github.com - git add tests/js-runners.test.ts - git diff --cached --check - git commit -m "Exercise adversarial JS runner parser cases" - git push From ef5f37441b13ba0cd3e21b44c1d549ed4a40e523 Mon Sep 17 00:00:00 2001 From: Felix Date: Sat, 15 Aug 2026 17:32:07 +0800 Subject: [PATCH 6/6] Remove one-time JS runner trigger --- .one-time-js-runner-trigger | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .one-time-js-runner-trigger diff --git a/.one-time-js-runner-trigger b/.one-time-js-runner-trigger deleted file mode 100644 index 5c33b15..0000000 --- a/.one-time-js-runner-trigger +++ /dev/null @@ -1 +0,0 @@ -trigger