From 86d203222dcb029fae39bf1ba139a596683a163e Mon Sep 17 00:00:00 2001 From: stevef Date: Fri, 17 Apr 2026 20:58:53 +0200 Subject: [PATCH] fix: properly check path arguments after flags in exec denyWritePaths --- pkg/tools/shell.go | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/pkg/tools/shell.go b/pkg/tools/shell.go index 1d789ede0..3b5119988 100644 --- a/pkg/tools/shell.go +++ b/pkg/tools/shell.go @@ -1049,14 +1049,31 @@ func (t *ExecTool) guardCommand(command, cwd string) string { if len(t.denyWritePaths) > 0 { words := strings.Fields(cmd) for i, word := range words { + // Skip flags but check their argument (next word) + if word == "-p" || word == "-rf" || word == "-r" || word == "-f" || word == "-d" { + // Check the next word as the actual path + if i+1 < len(words) { + nextWord := words[i+1] + for _, pattern := range t.denyWritePaths { + if pattern.MatchString(nextWord) { + return fmt.Sprintf("Command blocked: cannot write to %s (access denied)", nextWord) + } + // Also check path components + pathParts := strings.Split(nextWord, "/") + for _, part := range pathParts { + if pattern.MatchString(part) { + return fmt.Sprintf("Command blocked: cannot write to %s (access denied)", part) + } + } + } + } + continue + } for _, pattern := range t.denyWritePaths { if pattern.MatchString(word) { return fmt.Sprintf("Command blocked: cannot write to %s (access denied)", word) } // Also check path components like "skills" in "mkdir -p skills/my_skill" - if i >= 0 && (word == "-p" || word == "-rf" || word == "-r") { - continue - } pathParts := strings.Split(word, "/") for _, part := range pathParts { if pattern.MatchString(part) {