fix: unwrap env path carrier commands

This commit is contained in:
Peter Steinberger
2026-05-04 05:38:33 +01:00
parent cf1991d27d
commit 117364e2b9
5 changed files with 13 additions and 0 deletions

View File

@@ -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 <path>` 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.

View File

@@ -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",

View File

@@ -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",
]);

View File

@@ -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",

View File

@@ -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)"],