From 50896f203debab8796bd62e28b409652d0652054 Mon Sep 17 00:00:00 2001 From: Hakancan Date: Sun, 8 Mar 2026 23:01:02 +0000 Subject: [PATCH] fix: safety guard incorrectly blocks commands with URLs The absolutePathPattern regex was matching URL path components like //github.com as file system paths, causing commands containing URLs to be incorrectly blocked by the workspace restriction safety guard. For example, 'agent-browser open https://github.com' would be blocked because //github.com was treated as an absolute file path outside the working directory. The fix adds a check to skip any path match that starts with '//', as these are URL path components, not file system paths. Fixes #1203 --- pkg/tools/shell.go | 8 ++++++++ pkg/tools/shell_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/pkg/tools/shell.go b/pkg/tools/shell.go index b8a811d03..2edd0accb 100644 --- a/pkg/tools/shell.go +++ b/pkg/tools/shell.go @@ -339,6 +339,14 @@ func (t *ExecTool) guardCommand(command, cwd string) string { matches := absolutePathPattern.FindAllString(cmd, -1) for _, raw := range matches { + // Skip URL path components that look like they're from URLs. + // When a URL like "https://github.com" is parsed, the regex captures + // "//github.com" as a match (the path portion after "https:"). + // These double-slash prefixes indicate URL paths, not file system paths. + if strings.HasPrefix(raw, "//") { + continue + } + p, err := filepath.Abs(raw) if err != nil { continue diff --git a/pkg/tools/shell_test.go b/pkg/tools/shell_test.go index ff9ea4a15..cb5f1a305 100644 --- a/pkg/tools/shell_test.go +++ b/pkg/tools/shell_test.go @@ -443,3 +443,32 @@ func TestShellTool_CustomAllowPatterns(t *testing.T) { t.Errorf("'git push upstream main' should still be blocked by deny pattern") } } + +// TestShellTool_URLsNotBlocked verifies that commands containing URLs are not +// incorrectly blocked by the workspace restriction safety guard (issue #1203). +func TestShellTool_URLsNotBlocked(t *testing.T) { + tmpDir := t.TempDir() + tool, err := NewExecTool(tmpDir, true) + if err != nil { + t.Fatalf("unable to configure exec tool: %s", err) + } + + // These commands contain URLs and should NOT be blocked by workspace restriction. + // The URL path components (e.g., "//github.com") should be recognized as URLs, + // not as file system paths. + commands := []string{ + "agent-browser open https://github.com", + "curl https://api.example.com/data", + "wget http://example.com/file", + "browser open https://github.com/user/repo", + "fetch ftp://ftp.example.com/file.txt", + "git clone https://github.com/sipeed/picoclaw.git", + } + + for _, cmd := range commands { + result := tool.Execute(context.Background(), map[string]any{"command": cmd}) + if result.IsError && strings.Contains(result.ForLLM, "path outside working dir") { + t.Errorf("command with URL should not be blocked by workspace check: %s\n error: %s", cmd, result.ForLLM) + } + } +}