fix: allow http urls in exec workspace guard
This commit is contained in:
parent
46201fb679
commit
456a302b36
2 changed files with 37 additions and 2 deletions
|
|
@ -79,6 +79,10 @@ var (
|
||||||
// absolutePathPattern matches absolute file paths in commands (Unix and Windows).
|
// absolutePathPattern matches absolute file paths in commands (Unix and Windows).
|
||||||
absolutePathPattern = regexp.MustCompile(`[A-Za-z]:\\[^\\\"']+|/[^\s\"']+`)
|
absolutePathPattern = regexp.MustCompile(`[A-Za-z]:\\[^\\\"']+|/[^\s\"']+`)
|
||||||
|
|
||||||
|
// httpURLPattern matches HTTP(S) URLs so they can be excluded from path-based
|
||||||
|
// workspace checks. URLs are command arguments, not local filesystem paths.
|
||||||
|
httpURLPattern = regexp.MustCompile(`(?i)\bhttps?://[^\s"'<>]+`)
|
||||||
|
|
||||||
// safePaths are kernel pseudo-devices that are always safe to reference in
|
// safePaths are kernel pseudo-devices that are always safe to reference in
|
||||||
// commands, regardless of workspace restriction. They contain no user data
|
// commands, regardless of workspace restriction. They contain no user data
|
||||||
// and cannot cause destructive writes.
|
// and cannot cause destructive writes.
|
||||||
|
|
@ -327,7 +331,9 @@ func (t *ExecTool) guardCommand(command, cwd string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.restrictToWorkspace {
|
if t.restrictToWorkspace {
|
||||||
if strings.Contains(cmd, "..\\") || strings.Contains(cmd, "../") {
|
sanitizedCmd := stripHTTPURLs(cmd)
|
||||||
|
|
||||||
|
if strings.Contains(sanitizedCmd, "..\\") || strings.Contains(sanitizedCmd, "../") {
|
||||||
return "Command blocked by safety guard (path traversal detected)"
|
return "Command blocked by safety guard (path traversal detected)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -336,7 +342,7 @@ func (t *ExecTool) guardCommand(command, cwd string) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
matches := absolutePathPattern.FindAllString(cmd, -1)
|
matches := absolutePathPattern.FindAllString(sanitizedCmd, -1)
|
||||||
|
|
||||||
for _, raw := range matches {
|
for _, raw := range matches {
|
||||||
p, err := filepath.Abs(raw)
|
p, err := filepath.Abs(raw)
|
||||||
|
|
@ -362,6 +368,12 @@ func (t *ExecTool) guardCommand(command, cwd string) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func stripHTTPURLs(command string) string {
|
||||||
|
return httpURLPattern.ReplaceAllStringFunc(command, func(match string) string {
|
||||||
|
return strings.Repeat(" ", len(match))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (t *ExecTool) SetTimeout(timeout time.Duration) {
|
func (t *ExecTool) SetTimeout(timeout time.Duration) {
|
||||||
t.timeout = timeout
|
t.timeout = timeout
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -312,6 +312,29 @@ func TestShellTool_RestrictToWorkspace(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestShellTool_RestrictToWorkspace_AllowsHTTPURLs verifies that HTTP(S) URLs
|
||||||
|
// are not mistaken for absolute filesystem paths when workspace restriction is active.
|
||||||
|
func TestShellTool_RestrictToWorkspace_AllowsHTTPURLs(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
tool, err := NewExecTool(tmpDir, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to configure exec tool: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
commands := []string{
|
||||||
|
`echo "http://example.com"`,
|
||||||
|
`echo "https://test"`,
|
||||||
|
`echo "https://example.com/path/../still-a-url"`,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cmd := range commands {
|
||||||
|
result := tool.Execute(context.Background(), map[string]any{"command": cmd})
|
||||||
|
if result.IsError {
|
||||||
|
t.Fatalf("expected HTTP(S) URL to be allowed, command=%q error=%s", cmd, result.ForLLM)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestShellTool_DevNullAllowed verifies that /dev/null redirections are not blocked (issue #964).
|
// TestShellTool_DevNullAllowed verifies that /dev/null redirections are not blocked (issue #964).
|
||||||
func TestShellTool_DevNullAllowed(t *testing.T) {
|
func TestShellTool_DevNullAllowed(t *testing.T) {
|
||||||
tmpDir := t.TempDir()
|
tmpDir := t.TempDir()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue