From 8a469a12b2e269d2b540655c9579baa6d06426fb Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 8 Mar 2026 00:11:57 +0000 Subject: [PATCH] test(exec): dedupe wrapper boundary regressions --- src/infra/system-run-command.test.ts | 32 ++++--------- src/node-host/invoke-system-run.test.ts | 63 +++++++++---------------- 2 files changed, 31 insertions(+), 64 deletions(-) diff --git a/src/infra/system-run-command.test.ts b/src/infra/system-run-command.test.ts index 421f3522a69..fed52efe582 100644 --- a/src/infra/system-run-command.test.ts +++ b/src/infra/system-run-command.test.ts @@ -41,30 +41,14 @@ describe("system run command helpers", () => { }); test("extractShellCommandFromArgv unwraps known dispatch wrappers before shell wrappers", () => { - expect(extractShellCommandFromArgv(["/usr/bin/nice", "/bin/bash", "-lc", "echo hi"])).toBe( - "echo hi", - ); - expect( - extractShellCommandFromArgv([ - "/usr/bin/timeout", - "--signal=TERM", - "5", - "zsh", - "-lc", - "echo hi", - ]), - ).toBe("echo hi"); - expect( - extractShellCommandFromArgv([ - "/usr/bin/env", - "/usr/bin/env", - "/usr/bin/env", - "/usr/bin/env", - "/bin/sh", - "-c", - "echo hi", - ]), - ).toBe("echo hi"); + const cases = [ + ["/usr/bin/nice", "/bin/bash", "-lc", "echo hi"], + ["/usr/bin/timeout", "--signal=TERM", "5", "zsh", "-lc", "echo hi"], + ["/usr/bin/env", "/usr/bin/env", "/usr/bin/env", "/usr/bin/env", "/bin/sh", "-c", "echo hi"], + ]; + for (const argv of cases) { + expect(extractShellCommandFromArgv(argv)).toBe("echo hi"); + } }); test("extractShellCommandFromArgv supports fish and pwsh wrappers", () => { diff --git a/src/node-host/invoke-system-run.test.ts b/src/node-host/invoke-system-run.test.ts index 9b1fbecd8eb..43b6148b164 100644 --- a/src/node-host/invoke-system-run.test.ts +++ b/src/node-host/invoke-system-run.test.ts @@ -858,13 +858,14 @@ describe("handleSystemRunInvoke mac app exec host routing", () => { expectApprovalRequiredDenied({ sendNodeEvent, sendInvokeResult }); }); - it("denies env-wrapped shell payloads at the dispatch depth boundary", async () => { - if (process.platform === "win32") { - return; - } + async function expectNestedEnvShellDenied(params: { + depth: number; + markerName: string; + errorLabel: string; + }) { const { runCommand, sendInvokeResult, sendNodeEvent } = createInvokeSpies({ runCommand: vi.fn(async () => { - throw new Error("runCommand should not be called for depth-boundary shell wrappers"); + throw new Error(params.errorLabel); }), }); @@ -877,11 +878,11 @@ describe("handleSystemRunInvoke mac app exec host routing", () => { }, }), run: async ({ tempHome }) => { - const marker = path.join(tempHome, "depth4-pwned.txt"); + const marker = path.join(tempHome, params.markerName); await runSystemInvoke({ preferMacAppExecHost: false, command: buildNestedEnvShellCommand({ - depth: 4, + depth: params.depth, payload: `echo PWNED > ${marker}`, }), security: "allowlist", @@ -896,45 +897,27 @@ describe("handleSystemRunInvoke mac app exec host routing", () => { expect(runCommand).not.toHaveBeenCalled(); expectApprovalRequiredDenied({ sendNodeEvent, sendInvokeResult }); + } + + it("denies env-wrapped shell payloads at the dispatch depth boundary", async () => { + if (process.platform === "win32") { + return; + } + await expectNestedEnvShellDenied({ + depth: 4, + markerName: "depth4-pwned.txt", + errorLabel: "runCommand should not be called for depth-boundary shell wrappers", + }); }); it("denies nested env shell payloads when wrapper depth is exceeded", async () => { if (process.platform === "win32") { return; } - const { runCommand, sendInvokeResult, sendNodeEvent } = createInvokeSpies({ - runCommand: vi.fn(async () => { - throw new Error("runCommand should not be called for nested env depth overflow"); - }), + await expectNestedEnvShellDenied({ + depth: 5, + markerName: "pwned.txt", + errorLabel: "runCommand should not be called for nested env depth overflow", }); - - await withTempApprovalsHome({ - approvals: createAllowlistOnMissApprovals({ - agents: { - main: { - allowlist: [{ pattern: "/usr/bin/env" }], - }, - }, - }), - run: async ({ tempHome }) => { - const marker = path.join(tempHome, "pwned.txt"); - await runSystemInvoke({ - preferMacAppExecHost: false, - command: buildNestedEnvShellCommand({ - depth: 5, - payload: `echo PWNED > ${marker}`, - }), - security: "allowlist", - ask: "on-miss", - runCommand, - sendInvokeResult, - sendNodeEvent, - }); - expect(fs.existsSync(marker)).toBe(false); - }, - }); - - expect(runCommand).not.toHaveBeenCalled(); - expectApprovalRequiredDenied({ sendNodeEvent, sendInvokeResult }); }); });