fix(security): harden system.run companion command binding

This commit is contained in:
Peter Steinberger
2026-02-25 00:01:53 +00:00
parent 8680240f7e
commit 55cf92578d
6 changed files with 520 additions and 5 deletions

View File

@@ -121,6 +121,32 @@ describe("handleSystemRunInvoke mac app exec host routing", () => {
);
});
it("forwards canonical cmdText to mac app exec host for positional-argv shell wrappers", async () => {
const { runViaMacAppExecHost } = await runSystemInvoke({
preferMacAppExecHost: true,
command: ["/bin/sh", "-lc", '$0 "$1"', "/usr/bin/touch", "/tmp/marker"],
runViaResponse: {
ok: true,
payload: {
success: true,
stdout: "app-ok",
stderr: "",
timedOut: false,
exitCode: 0,
error: null,
},
},
});
expect(runViaMacAppExecHost).toHaveBeenCalledWith({
approvals: expect.anything(),
request: expect.objectContaining({
command: ["/bin/sh", "-lc", '$0 "$1"', "/usr/bin/touch", "/tmp/marker"],
rawCommand: '/bin/sh -lc "$0 \\"$1\\"" /usr/bin/touch /tmp/marker',
}),
});
});
it("handles transparent env wrappers in allowlist mode", async () => {
const { runCommand, sendInvokeResult } = await runSystemInvoke({
preferMacAppExecHost: false,

View File

@@ -291,7 +291,6 @@ export async function handleSystemRunInvoke(opts: HandleSystemRunInvokeOptions):
}
const argv = command.argv;
const rawCommand = command.rawCommand ?? "";
const shellCommand = command.shellCommand;
const cmdText = command.cmdText;
const agentId = opts.params.agentId?.trim() || undefined;
@@ -388,7 +387,9 @@ export async function handleSystemRunInvoke(opts: HandleSystemRunInvokeOptions):
if (useMacAppExec) {
const execRequest: ExecHostRequest = {
command: plannedAllowlistArgv ?? argv,
rawCommand: rawCommand || shellCommand || null,
// Forward canonical display text so companion approval/prompt surfaces bind to
// the exact command context already validated on the node-host.
rawCommand: cmdText || null,
cwd: opts.params.cwd ?? null,
env: envOverrides ?? null,
timeoutMs: opts.params.timeoutMs ?? null,