@@ -47,25 +47,14 @@ pub struct ExecuteCommand {
4747 pub summary : Option < String > ,
4848}
4949
50- impl ExecuteCommand { //REMOVEMEBUTIMPT actual tool call verification
50+ impl ExecuteCommand { //REMOVEME guard point
5151 pub fn requires_acceptance ( & self , allowed_commands : Option < & Vec < String > > , allow_read_only : bool ) -> bool {
5252 // Always require acceptance for multi-line commands.
5353 if self . command . contains ( "\n " ) || self . command . contains ( "\r " ) {
5454 return true ;
5555 }
5656
5757 let default_arr = vec ! [ ] ;
58- let allowed_commands = allowed_commands. unwrap_or ( & default_arr) ;
59-
60- let has_regex_match = allowed_commands
61- . iter ( )
62- . map ( |cmd| Regex :: new ( & format ! ( r"\A{}\z" , cmd) ) )
63- . filter ( Result :: is_ok)
64- . flatten ( )
65- . any ( |regex| regex. is_match ( & self . command ) ) ;
66- if has_regex_match {
67- return false ;
68- }
6958
7059 let Some ( args) = shlex:: split ( & self . command ) else {
7160 return true ;
@@ -100,6 +89,17 @@ impl ExecuteCommand { //REMOVEMEBUTIMPT actual tool call verification
10089 if !current_cmd. is_empty ( ) {
10190 all_commands. push ( current_cmd) ;
10291 }
92+ let allowed_commands = allowed_commands. unwrap_or ( & default_arr) ;
93+
94+ let has_regex_match = allowed_commands
95+ . iter ( )
96+ . map ( |cmd| Regex :: new ( & format ! ( r"\A{}\z" , cmd) ) )
97+ . filter ( Result :: is_ok)
98+ . flatten ( )
99+ . any ( |regex| regex. is_match ( & self . command ) ) ;
100+ if has_regex_match {
101+ return false ;
102+ }
103103
104104 // Check if each command in the pipe chain starts with a safe command
105105 for cmd_args in all_commands {
@@ -294,7 +294,7 @@ mod tests {
294294 } ;
295295
296296 #[ test]
297- fn test_requires_acceptance_for_readonly_commands ( ) { //REMOVEMEBUTIMPT tests unit tests you should write some
297+ fn test_requires_acceptance_for_readonly_commands ( ) {
298298 let cmds = & [
299299 // Safe commands
300300 ( "ls ~" , false ) ,
@@ -423,8 +423,19 @@ mod tests {
423423 ( "command subcommand a=0123456789 b=0123456789" , false ) ,
424424 ( "command subcommand a=0123456789 b=012345678" , true ) ,
425425 ( "command subcommand alternate a=0123456789 b=0123456789" , true ) ,
426- // Control characters ignored due to direct allowed_command_regex match
427- ( "command subcommand && command subcommand" , false ) ,
426+ // dangerous patterns
427+ ( "echo 'test<(data'" , true ) ,
428+ ( "echo 'test$(data)'" , true ) ,
429+ ( "echo 'test`data`'" , true ) ,
430+ ( "echo 'test' > output.txt" , true ) ,
431+ ( "echo 'test data' && touch main.py" , true ) ,
432+ ( "echo 'test' || rm file" , true ) ,
433+ ( "echo 'test' & background" , true ) ,
434+ ( "echo 'test data'; touch main.py" , true ) ,
435+ ( "echo $HOME" , true ) ,
436+ ( "echo 'test\n rm file'" , true ) ,
437+ ( "echo 'test\r rm file'" , true ) ,
438+ ( "IFS=/ malicious" , true ) ,
428439 ] ;
429440 for ( cmd, expected) in cmds {
430441 let tool = serde_json:: from_value :: < ExecuteCommand > ( serde_json:: json!( {
0 commit comments