From 28a49aaa34398b3b69302b3d7769a50eae1d0c26 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 13 Mar 2026 20:37:29 +0000 Subject: [PATCH] fix: harden powershell wrapper detection --- CHANGELOG.md | 1 + src/infra/shell-inline-command.test.ts | 15 +++++++++++++++ src/infra/shell-inline-command.ts | 2 ++ src/infra/system-run-command.test.ts | 2 ++ 4 files changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0d512e9c51..688f7edd549 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ Docs: https://docs.openclaw.ai - Config/discovery: accept `discovery.wideArea.domain` in strict config validation so unicast DNS-SD gateway configs no longer fail with an unrecognized-key error. (#35615) Thanks @ingyukoh. - Security/exec approvals: unwrap more `pnpm` runtime forms during approval binding, including `pnpm --reporter ... exec` and direct `pnpm node` file runs, with matching regression coverage and docs updates. - Security/exec approvals: fail closed for Perl `-M` and `-I` approval flows so preload and load-path module resolution stays outside approval-backed runtime execution unless the operator uses a broader explicit trust path. +- Security/exec approvals: recognize PowerShell `-File` and `-f` wrapper forms during inline-command extraction so approval and command-analysis paths treat file-based PowerShell launches like the existing `-Command` variants. - Security/external content: strip zero-width and soft-hyphen marker-splitting characters during boundary sanitization so spoofed `EXTERNAL_UNTRUSTED_CONTENT` markers fall back to the existing hardening path instead of bypassing marker normalization. - Control UI/insecure auth: preserve explicit shared token and password auth on plain-HTTP Control UI connects so LAN and reverse-proxy sessions no longer drop shared auth before the first WebSocket handshake. (#45088) Thanks @velvet-shark. - macOS/onboarding: avoid self-restarting freshly bootstrapped launchd gateways and give new daemon installs longer to become healthy, so `openclaw onboard --install-daemon` no longer false-fails on slower Macs and fresh VM snapshots. diff --git a/src/infra/shell-inline-command.test.ts b/src/infra/shell-inline-command.test.ts index 8ac552f9fee..1c5892eff59 100644 --- a/src/infra/shell-inline-command.test.ts +++ b/src/infra/shell-inline-command.test.ts @@ -22,6 +22,21 @@ describe("resolveInlineCommandMatch", () => { command: "Get-ChildItem", valueTokenIndex: 2, }); + expect( + resolveInlineCommandMatch(["pwsh", "-File", "script.ps1"], POWERSHELL_INLINE_COMMAND_FLAGS), + ).toEqual({ + command: "script.ps1", + valueTokenIndex: 2, + }); + expect( + resolveInlineCommandMatch( + ["powershell", "-f", "script.ps1"], + POWERSHELL_INLINE_COMMAND_FLAGS, + ), + ).toEqual({ + command: "script.ps1", + valueTokenIndex: 2, + }); }); it("supports combined -c forms only when enabled", () => { diff --git a/src/infra/shell-inline-command.ts b/src/infra/shell-inline-command.ts index 9e0f33627ab..e5b46640c13 100644 --- a/src/infra/shell-inline-command.ts +++ b/src/infra/shell-inline-command.ts @@ -3,6 +3,8 @@ export const POWERSHELL_INLINE_COMMAND_FLAGS = new Set([ "-c", "-command", "--command", + "-f", + "-file", "-encodedcommand", "-enc", "-e", diff --git a/src/infra/system-run-command.test.ts b/src/infra/system-run-command.test.ts index e9e5d17da2e..ea3ec9ffdf5 100644 --- a/src/infra/system-run-command.test.ts +++ b/src/infra/system-run-command.test.ts @@ -55,6 +55,8 @@ describe("system run command helpers", () => { test("extractShellCommandFromArgv supports fish and pwsh wrappers", () => { expect(extractShellCommandFromArgv(["fish", "-c", "echo hi"])).toBe("echo hi"); expect(extractShellCommandFromArgv(["pwsh", "-Command", "Get-Date"])).toBe("Get-Date"); + expect(extractShellCommandFromArgv(["pwsh", "-File", "script.ps1"])).toBe("script.ps1"); + expect(extractShellCommandFromArgv(["powershell", "-f", "script.ps1"])).toBe("script.ps1"); expect(extractShellCommandFromArgv(["pwsh", "-EncodedCommand", "ZQBjAGgAbwA="])).toBe( "ZQBjAGgAbwA=", );