Fix: calling URLs with curl

Calling URLs via curl results in the error: “Command blocked by safety guard (path outside working dir)”. This commit fixes the problem.

My changes to guardCommand ensure that the command is split into its individual parts (command + options/flags + arguments) and that each part is checked individually. In addition, web URLs are excluded from the check.
This commit is contained in:
Björn Renzel 2026-03-01 19:06:20 +01:00 committed by GitHub
parent 3926585786
commit 91ebe2fde7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -5,11 +5,13 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"net/url"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"regexp" "regexp"
"runtime" "runtime"
"strconv"
"strings" "strings"
"time" "time"
@ -75,6 +77,9 @@ 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\"']+`)
// split command in command + options/flags + arguments
splitPattern = regexp.MustCompile(`("[^"]*"|'[^']*'|[\S]+)+`)
) )
func NewExecTool(workingDir string, restrict bool) (*ExecTool, error) { func NewExecTool(workingDir string, restrict bool) (*ExecTool, error) {
@ -286,16 +291,33 @@ func (t *ExecTool) guardCommand(command, cwd string) string {
} }
if t.restrictToWorkspace { if t.restrictToWorkspace {
if strings.Contains(cmd, "..\\") || strings.Contains(cmd, "../") {
return "Command blocked by safety guard (path traversal detected)"
}
cwdPath, err := filepath.Abs(cwd) cwdPath, err := filepath.Abs(cwd)
if err != nil { if err != nil {
return "" cwdPath = ""
} }
matches := absolutePathPattern.FindAllString(cmd, -1) parts := splitPattern.FindAllString(cmd, -1)
for _, part := range parts {
unquoted, err := strconv.Unquote(part)
if err != nil {
unquoted = part
}
u, err := url.ParseRequestURI(unquoted)
if err == nil && u.Scheme != "" && u.Host != "" {
continue
}
if strings.Contains(part, "..\\") || strings.Contains(part, "../") {
return "Command blocked by safety guard (path traversal detected)"
}
if cwdPath == "" {
continue
}
matches := absolutePathPattern.FindAllString(part, -1)
for _, raw := range matches { for _, raw := range matches {
p, err := filepath.Abs(raw) p, err := filepath.Abs(raw)
@ -313,6 +335,7 @@ func (t *ExecTool) guardCommand(command, cwd string) string {
} }
} }
} }
}
return "" return ""
} }