From 63b171b1a2f75563c4f872fde03470aad9002445 Mon Sep 17 00:00:00 2001 From: John Richmond <5629+jr@users.noreply.github.com> Date: Mon, 29 Sep 2025 15:43:28 -0700 Subject: [PATCH] More patterns --- .../src/utils/__tests__/command-validation.spec.ts | 4 ++++ webview-ui/src/utils/command-validation.ts | 11 +++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/webview-ui/src/utils/__tests__/command-validation.spec.ts b/webview-ui/src/utils/__tests__/command-validation.spec.ts index 2427fc64b2..6180e6d28e 100644 --- a/webview-ui/src/utils/__tests__/command-validation.spec.ts +++ b/webview-ui/src/utils/__tests__/command-validation.spec.ts @@ -301,6 +301,8 @@ ls -la || echo "Failed"` it("detects zsh glob qualifiers with code execution (e:...:)", () => { // Basic glob qualifier with command execution expect(containsDangerousSubstitution("ls *(e:whoami:)")).toBe(true) + // Zsh extended glob with qualifier list and brace-arg: e{'whoami'} as reported + expect(containsDangerousSubstitution("ls *(.e{'whoami'})")).toBe(true) // Various glob patterns with code execution expect(containsDangerousSubstitution("cat ?(e:rm -rf /:)")).toBe(true) @@ -1043,6 +1045,8 @@ describe("Unified Command Decision Functions", () => { const globExploit = "ls *(e:whoami:)" // Even though 'ls' might be allowed, the dangerous pattern prevents auto-approval expect(getCommandDecision(globExploit, ["ls", "echo"], [])).toBe("ask_user") + // Zsh extended glob with qualifier list and brace-arg form + expect(getCommandDecision("ls *(.e{'whoami'})", ["ls", "echo"], [])).toBe("ask_user") // Various forms should all be blocked expect(getCommandDecision("cat ?(e:rm -rf /:)", ["cat"], [])).toBe("ask_user") diff --git a/webview-ui/src/utils/command-validation.ts b/webview-ui/src/utils/command-validation.ts index a4c4f8c107..b92aba0d36 100644 --- a/webview-ui/src/utils/command-validation.ts +++ b/webview-ui/src/utils/command-validation.ts @@ -107,10 +107,13 @@ export function containsDangerousSubstitution(source: string): boolean { // =(...) creates a temporary file containing the output of the command, but executes it const zshProcessSubstitution = /=\([^)]+\)/.test(source) - // Check for zsh glob qualifiers with code execution (e:...:) - // Patterns like *(e:whoami:) or ?(e:rm -rf /:) execute commands during glob expansion - // This regex matches patterns like *(e:...:), ?(e:...:), +(e:...:), @(e:...:), !(e:...:) - const zshGlobQualifier = /[*?+@!]\(e:[^:]+:\)/.test(source) + // Check for zsh glob qualifiers with code execution via the "e" qualifier + // This must detect multiple zsh forms that execute code during glob expansion: + // - Classic: *(e:whoami:) or ?(e:rm -rf /:) etc. + // - With other qualifiers: *(.e:whoami:) (dot means "plain files" plus e:...) + // - Brace/quoted argument forms: *(e{'whoami'}), *(.e{'whoami'}), *(e{"whoami"}), *(.e{"whoami"}) + // Any appearance of an "e" qualifier with an argument inside a glob qualifier list is dangerous. + const zshGlobQualifier = /\([^)]*e\s*(?::[^:]*:|\{[^}]*\}|'[^']*'|"[^"]*")[^)]*\)/.test(source) // Check for $"..." string interpolation with command substitution // $"..." is a bash feature for translated strings that allows command substitution inside