From ae2c91303708f4152a7637bbbd18dcd34169e64e Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Mon, 7 Sep 2026 05:01:44 -0400 Subject: [PATCH 1/2] fix: distinguish benchmark executable lookups from device calls --- scripts/agent-benchmark/run-guards.mjs | 6 ++++- scripts/agent-benchmark/run-guards.test.mjs | 30 +++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/scripts/agent-benchmark/run-guards.mjs b/scripts/agent-benchmark/run-guards.mjs index c87b5c4a..361fd6e5 100644 --- a/scripts/agent-benchmark/run-guards.mjs +++ b/scripts/agent-benchmark/run-guards.mjs @@ -112,7 +112,11 @@ export function agentDeviceIsolationInvalidReasons(commands, expectedPrefix) { if (segments.some((command) => /(?:^|\s)agent-device\s+daemon\s+stop(?:\s|$)/.test(command))) { reasons.push('agent-device-daemon-recovery-inside-timer'); } - const deviceCommands = segments.filter((command) => /(?:^|\s)agent-device(?:\s|$)/.test(command)); + const lookup = + /^(?:command\s+-[vV]|which|type|whence)\s+(?:[\w./-]+\s+)*agent-device(?:\s+[\w./-]+)*(?:\s+\d*>\s*[\w./-]*)?$/; + const deviceCommands = segments.filter( + (command) => /(?:^|\s)agent-device(?:\s|$)/.test(command) && !lookup.test(command), + ); if (deviceCommands.some((command) => !command.startsWith(expectedPrefix))) { reasons.push('agent-device-run-session-not-applied'); } diff --git a/scripts/agent-benchmark/run-guards.test.mjs b/scripts/agent-benchmark/run-guards.test.mjs index ca8c192a..6a19ab78 100644 --- a/scripts/agent-benchmark/run-guards.test.mjs +++ b/scripts/agent-benchmark/run-guards.test.mjs @@ -56,6 +56,36 @@ describe('agent-device session isolation', () => { } }); + it('does not treat literal executable discovery as a device invocation', () => { + for (const command of [ + 'command -v agent-device', + 'command -V agent-device 2>&1', + 'which node agent-device adb', + 'type agent-device 2>/dev/null', + 'whence agent-device', + `command -v agent-device 2>&1; ${prefix}snapshot`, + `/bin/zsh -lc 'command -v agent-device 2>&1'`, + ]) { + expect(agentDeviceIsolationInvalidReasons([{ command }], prefix)).toEqual([]); + } + }); + + it('does not let executable discovery hide an actual unscoped invocation', () => { + for (const command of [ + 'command agent-device snapshot', + 'command -p agent-device snapshot', + 'command -v agent-device; agent-device snapshot', + 'which agent-device && agent-device snapshot', + 'command -v agent-device $(agent-device snapshot)', + 'command -v agent-device >$(agent-device snapshot)', + 'type agent-device `agent-device snapshot`', + ]) { + expect(agentDeviceIsolationInvalidReasons([{ command }], prefix)).toContain( + 'agent-device-run-session-not-applied', + ); + } + }); + it('rejects delayed daemon recovery even with the correct session', () => { expect(agentDeviceIsolationInvalidReasons([{ command: `sleep 5; ${prefix}daemon stop --clean` }], prefix)).toEqual([ 'agent-device-daemon-recovery-inside-timer', From 9643f89c72f910c57d45f4a5580b5f08260efc37 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Mon, 7 Sep 2026 05:10:04 -0400 Subject: [PATCH 2/2] fix: preserve invocation checks around shell lookups --- scripts/agent-benchmark/run-guards.mjs | 11 ++++++----- scripts/agent-benchmark/run-guards.test.mjs | 13 +++++++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/scripts/agent-benchmark/run-guards.mjs b/scripts/agent-benchmark/run-guards.mjs index 361fd6e5..3e206933 100644 --- a/scripts/agent-benchmark/run-guards.mjs +++ b/scripts/agent-benchmark/run-guards.mjs @@ -94,6 +94,7 @@ export function shellCommandSegments(command) { continue; } const next = source[index + 1]; + if (char === '&' && (source[index - 1] === '>' || source[index - 1] === '<' || next === '>')) continue; const separator = char === '\n' || char === ';' || char === '|' || char === '&'; if (!separator) continue; const segment = source.slice(start, index).trim(); @@ -109,14 +110,14 @@ export function shellCommandSegments(command) { export function agentDeviceIsolationInvalidReasons(commands, expectedPrefix) { const segments = commands.flatMap((command) => shellCommandSegments(command.command)); const reasons = []; - if (segments.some((command) => /(?:^|\s)agent-device\s+daemon\s+stop(?:\s|$)/.test(command))) { - reasons.push('agent-device-daemon-recovery-inside-timer'); - } const lookup = - /^(?:command\s+-[vV]|which|type|whence)\s+(?:[\w./-]+\s+)*agent-device(?:\s+[\w./-]+)*(?:\s+\d*>\s*[\w./-]*)?$/; + /^(?:command\s+-[vV]|which|type|whence)\s+(?:[\w./-]+\s+)*agent-device(?:\s+[\w./-]+)*(?:\s+(?:\d*>|&>)\s*(?:&\d+|[\w./-]+))?$/; const deviceCommands = segments.filter( - (command) => /(?:^|\s)agent-device(?:\s|$)/.test(command) && !lookup.test(command), + (command) => /(?:^|[\s(`])agent-device(?:\s|[)`]|$)/.test(command) && !lookup.test(command), ); + if (deviceCommands.some((command) => /(?:^|[\s(`])agent-device\s+daemon\s+stop(?:\s|[)`]|$)/.test(command))) { + reasons.push('agent-device-daemon-recovery-inside-timer'); + } if (deviceCommands.some((command) => !command.startsWith(expectedPrefix))) { reasons.push('agent-device-run-session-not-applied'); } diff --git a/scripts/agent-benchmark/run-guards.test.mjs b/scripts/agent-benchmark/run-guards.test.mjs index 6a19ab78..d6f5ec7c 100644 --- a/scripts/agent-benchmark/run-guards.test.mjs +++ b/scripts/agent-benchmark/run-guards.test.mjs @@ -63,6 +63,8 @@ describe('agent-device session isolation', () => { 'which node agent-device adb', 'type agent-device 2>/dev/null', 'whence agent-device', + 'command -v agent-device daemon stop', + 'command -v agent-device &>/dev/null', `command -v agent-device 2>&1; ${prefix}snapshot`, `/bin/zsh -lc 'command -v agent-device 2>&1'`, ]) { @@ -78,6 +80,11 @@ describe('agent-device session isolation', () => { 'which agent-device && agent-device snapshot', 'command -v agent-device $(agent-device snapshot)', 'command -v agent-device >$(agent-device snapshot)', + 'command -v agent-device 2>&$(agent-device snapshot)', + 'command -v agent-device 2>&$(agent-device daemon stop)', + 'command -v agent-device; $(agent-device snapshot)', + 'command -v agent-device && $(agent-device daemon stop)', + 'command -v agent-device & `agent-device snapshot`', 'type agent-device `agent-device snapshot`', ]) { expect(agentDeviceIsolationInvalidReasons([{ command }], prefix)).toContain( @@ -90,6 +97,12 @@ describe('agent-device session isolation', () => { expect(agentDeviceIsolationInvalidReasons([{ command: `sleep 5; ${prefix}daemon stop --clean` }], prefix)).toEqual([ 'agent-device-daemon-recovery-inside-timer', ]); + expect( + agentDeviceIsolationInvalidReasons( + [{ command: 'command -v agent-device && $(agent-device daemon stop)' }], + prefix, + ), + ).toEqual(['agent-device-daemon-recovery-inside-timer', 'agent-device-run-session-not-applied']); }); });