diff --git a/CHANGELOG.md b/CHANGELOG.md index 9adf8d6a6ac..7d01feaa307 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ Docs: https://docs.openclaw.ai - Plugins/loader: keep bundled plugin package `test-api.js` aliases behind private QA mode, so source transforms do not expose test-only public surfaces during normal plugin loading. Thanks @vincentkoc. - Gateway/startup: start cron and record the post-ready memory trace even when deferred maintenance timers fail after readiness, so a non-fatal timer setup issue does not silently leave scheduled jobs idle. Thanks @vincentkoc. +- Exec approvals: unwrap BSD/macOS `env -P ` carrier commands before approval-command and strict inline-eval checks, so `/approve` shell execution and inline interpreter payloads are still blocked behind that env form. - Agents/session status: keep semantic `session_status({ sessionKey: "current" })` on the live run session even before that run has a persisted session-store entry, instead of falling back to the sandbox policy key. Thanks @vincentkoc. - QA/Slack: resolve bundled official plugin public-surface package aliases during source-mode QA runs, so release Slack live validation can load `@openclaw/slack/api.js` without workspace symlinks. Thanks @vincentkoc. - Codex: pass the live run session key into app-server dynamic tools when sandbox policy uses a separate session key, so `session_status({ sessionKey: "current" })` reports the active run instead of the sandbox policy key. Thanks @vincentkoc. diff --git a/src/agents/bash-tools.exec.path.test.ts b/src/agents/bash-tools.exec.path.test.ts index 7ada778c3e3..f2a70df60c8 100644 --- a/src/agents/bash-tools.exec.path.test.ts +++ b/src/agents/bash-tools.exec.path.test.ts @@ -337,6 +337,7 @@ describe("exec host env validation", () => { "env --ignore-environment /approve abc123 allow-once", "env -i FOO=1 /approve abc123 allow-once", "env -S '/approve abc123 deny'", + "env -P /usr/bin /approve abc123 deny", "env -iS'/approve abc123 deny'", "env -S '/approve abc123' deny", "env -iS'/approve abc123' deny", diff --git a/src/infra/command-analysis/risks.test.ts b/src/infra/command-analysis/risks.test.ts index 6ae653329e4..5855ef2dc9e 100644 --- a/src/infra/command-analysis/risks.test.ts +++ b/src/infra/command-analysis/risks.test.ts @@ -54,6 +54,9 @@ describe("command-analysis risks", () => { expect(detectInlineEvalArgv(["env", "-iS", "python3 -c 'print(1)'"])?.flag).toBe("-c"); expect(detectInlineEvalArgv(["env", "-S", "python3 -c", "print(1)"])?.flag).toBe("-c"); expect(detectInlineEvalArgv(["env", "-iSpython3 -c", "print(1)"])?.flag).toBe("-c"); + expect(detectInlineEvalArgv(["env", "-P", "/usr/bin", "python3", "-c", "print(1)"])?.flag).toBe( + "-c", + ); expect(detectInlineEvalArgv(["command", "node", "--eval", "1"])?.flag).toBe("--eval"); expect(detectInlineEvalArgv(["env", "-S", 'python3 -c "print(1)"'])?.flag).toBe("-c"); expect(detectInlineEvalArgv(["python3", "script.py"])).toBeNull(); @@ -174,6 +177,9 @@ describe("command-analysis risks", () => { "bash -lc /approve abc deny", "/approve abc deny", ]); + expect(buildCommandPayloadCandidates(["env", "-P", "/usr/bin", "/approve", "abc"])).toEqual([ + "/approve abc", + ]); expect(buildCommandPayloadCandidates(["exec", "-a", "openclaw", "/approve", "abc"])).toEqual([ "/approve abc", ]); diff --git a/src/infra/command-carriers.ts b/src/infra/command-carriers.ts index fa5439c9650..f7a978e0170 100644 --- a/src/infra/command-carriers.ts +++ b/src/infra/command-carriers.ts @@ -11,6 +11,7 @@ const COMMAND_EXECUTING_OPTIONS = new Set(["-p"]); const COMMAND_QUERY_OPTIONS = new Set(["-v", "-V"]); const ENV_OPTIONS_WITH_VALUE = new Set([ "-C", + "-P", "-S", "-s", "-u", diff --git a/src/infra/exec-wrapper-resolution.test.ts b/src/infra/exec-wrapper-resolution.test.ts index 4679580d7eb..32d87d73bdc 100644 --- a/src/infra/exec-wrapper-resolution.test.ts +++ b/src/infra/exec-wrapper-resolution.test.ts @@ -116,6 +116,10 @@ describe("unwrapEnvInvocation", () => { argv: ["env", "--chdir=/tmp", "pwsh", "-Command", "Get-Date"], expected: ["pwsh", "-Command", "Get-Date"], }, + { + argv: ["env", "-P", "/usr/bin", "python3", "-c", "print(1)"], + expected: ["python3", "-c", "print(1)"], + }, { argv: ["env", "-S", "python3 -c", "print(1)"], expected: ["python3", "-c", "print(1)"],