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"
"errors"
"fmt"
"net/url"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"time"
@ -75,6 +77,9 @@ var (
// absolutePathPattern matches absolute file paths in commands (Unix and Windows).
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) {
@ -286,30 +291,48 @@ func (t *ExecTool) guardCommand(command, cwd string) string {
}
if t.restrictToWorkspace {
if strings.Contains(cmd, "..\\") || strings.Contains(cmd, "../") {
return "Command blocked by safety guard (path traversal detected)"
}
cwdPath, err := filepath.Abs(cwd)
if err != nil {
return ""
cwdPath = ""
}
matches := absolutePathPattern.FindAllString(cmd, -1)
for _, raw := range matches {
p, err := filepath.Abs(raw)
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
}
rel, err := filepath.Rel(cwdPath, p)
if err != nil {
if strings.Contains(part, "..\\") || strings.Contains(part, "../") {
return "Command blocked by safety guard (path traversal detected)"
}
if cwdPath == "" {
continue
}
if strings.HasPrefix(rel, "..") {
return "Command blocked by safety guard (path outside working dir)"
matches := absolutePathPattern.FindAllString(part, -1)
for _, raw := range matches {
p, err := filepath.Abs(raw)
if err != nil {
continue
}
rel, err := filepath.Rel(cwdPath, p)
if err != nil {
continue
}
if strings.HasPrefix(rel, "..") {
return "Command blocked by safety guard (path outside working dir)"
}
}
}
}