فهرست منبع

fix: avoid zsh process-substitution false positives in assignments (#11365)

Hannes Rudolph 4 روز پیش
والد
کامیت
d4cf3211e7
2فایلهای تغییر یافته به همراه41 افزوده شده و 2 حذف شده
  1. 39 0
      src/core/auto-approval/__tests__/commands.spec.ts
  2. 2 2
      src/core/auto-approval/commands.ts

+ 39 - 0
src/core/auto-approval/__tests__/commands.spec.ts

@@ -0,0 +1,39 @@
+import { containsDangerousSubstitution, getCommandDecision } from "../commands"
+
+describe("containsDangerousSubstitution", () => {
+	describe("zsh array assignments (should NOT be flagged)", () => {
+		it("should return false for files=(a b c)", () => {
+			expect(containsDangerousSubstitution("files=(a b c)")).toBe(false)
+		})
+
+		it("should return false for var=(item1 item2)", () => {
+			expect(containsDangerousSubstitution("var=(item1 item2)")).toBe(false)
+		})
+
+		it("should return false for x=(hello)", () => {
+			expect(containsDangerousSubstitution("x=(hello)")).toBe(false)
+		})
+	})
+
+	describe("zsh process substitution (should be flagged)", () => {
+		it("should return true for standalone =(whoami)", () => {
+			expect(containsDangerousSubstitution("=(whoami)")).toBe(true)
+		})
+
+		it("should return true for =(ls) with leading space", () => {
+			expect(containsDangerousSubstitution(" =(ls)")).toBe(true)
+		})
+
+		it("should return true for echo =(cat /etc/passwd)", () => {
+			expect(containsDangerousSubstitution("echo =(cat /etc/passwd)")).toBe(true)
+		})
+	})
+})
+
+describe("getCommandDecision", () => {
+	it("should auto_approve array assignment command with wildcard allowlist", () => {
+		const command = 'files=(a.ts b.ts); for f in "${files[@]}"; do echo "$f"; done'
+		const result = getCommandDecision(command, ["*"])
+		expect(result).toBe("auto_approve")
+	})
+})

+ 2 - 2
src/core/auto-approval/commands.ts

@@ -13,7 +13,7 @@ import { parseCommand } from "../../shared/parse-command"
  * - ${var=value} with escape sequences - Can embed commands via \140 (backtick), \x60, or \u0060
  * - ${var=value} with escape sequences - Can embed commands via \140 (backtick), \x60, or \u0060
  * - ${!var} - Indirect variable references
  * - ${!var} - Indirect variable references
  * - <<<$(...) or <<<`...` - Here-strings with command substitution
  * - <<<$(...) or <<<`...` - Here-strings with command substitution
- * - =(...) - Zsh process substitution that executes commands
+ * - =(...) - Zsh process substitution that executes commands (array assignments like `var=(...)` are excluded)
  * - *(e:...:) or similar - Zsh glob qualifiers with code execution
  * - *(e:...:) or similar - Zsh glob qualifiers with code execution
  *
  *
  * @param source - The command string to analyze
  * @param source - The command string to analyze
@@ -46,7 +46,7 @@ export function containsDangerousSubstitution(source: string): boolean {
 
 
 	// Check for zsh process substitution =(...) which executes commands
 	// Check for zsh process substitution =(...) which executes commands
 	// =(...) creates a temporary file containing the output of the command, but executes it
 	// =(...) creates a temporary file containing the output of the command, but executes it
-	const zshProcessSubstitution = /=\([^)]+\)/.test(source)
+	const zshProcessSubstitution = /(?<![a-zA-Z0-9_])=\([^)]+\)/.test(source)
 
 
 	// Check for zsh glob qualifiers with code execution (e:...:)
 	// Check for zsh glob qualifiers with code execution (e:...:)
 	// Patterns like *(e:whoami:) or ?(e:rm -rf /:) execute commands during glob expansion
 	// Patterns like *(e:whoami:) or ?(e:rm -rf /:) execute commands during glob expansion