Skip to content

Commit 2d20582

Browse files
committed
feat: add technical path protection to tools
- SetProtectedPaths() / GetProtectedPaths() to configure protected paths - isPathProtected() checks if a path starts with any protected prefix - WriteFileTool and EditFileTool reject protected paths - BashTool blocks dangerous patterns: rm -rf, git push --force, chmod 777, pipe-to-sh, etc. - Protection is opt-in via SetProtectedPaths()
1 parent e7f45e6 commit 2d20582

1 file changed

Lines changed: 48 additions & 0 deletions

File tree

tools.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,45 @@ import (
1111
"time"
1212
)
1313

14+
var protectedPaths []string
15+
16+
var dangerousPatterns = []string{
17+
"rm -rf",
18+
"git push --force",
19+
"git push -f",
20+
"--force-with-lease",
21+
"chmod -R 777",
22+
"> /etc/",
23+
"curl .* | sh",
24+
"wget .* | sh",
25+
}
26+
27+
func SetProtectedPaths(paths []string) {
28+
protectedPaths = paths
29+
}
30+
31+
func GetProtectedPaths() []string {
32+
return protectedPaths
33+
}
34+
35+
func isPathProtected(path string) bool {
36+
for _, p := range protectedPaths {
37+
if strings.HasPrefix(path, p) {
38+
return true
39+
}
40+
}
41+
return false
42+
}
43+
44+
func isCommandDangerous(cmd string) bool {
45+
for _, pattern := range dangerousPatterns {
46+
if strings.Contains(cmd, pattern) {
47+
return true
48+
}
49+
}
50+
return false
51+
}
52+
1453
// DefaultTools returns all built-in tools available to the agent.
1554
func DefaultTools(repoPath string) []Tool {
1655
return []Tool{
@@ -36,6 +75,9 @@ func BashTool(repoPath string) Tool {
3675
if cmd == "" {
3776
return "", fmt.Errorf("cmd is required")
3877
}
78+
if isCommandDangerous(cmd) {
79+
return "", fmt.Errorf("command contains dangerous pattern: %s", cmd)
80+
}
3981
ctx, cancel := context.WithTimeout(ctx, 60*time.Second)
4082
defer cancel()
4183

@@ -71,6 +113,9 @@ func WriteFileTool(repoPath string) Tool {
71113
Description: "Write or overwrite a file in the repo.\nArgs: {\"path\": \"internal/agent/agent.go\", \"content\": \"...\"}",
72114
Execute: func(ctx context.Context, args map[string]string) (string, error) {
73115
path := filepath.Join(repoPath, args["path"])
116+
if isPathProtected(path) {
117+
return "", fmt.Errorf("write to %s is protected", args["path"])
118+
}
74119
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
75120
return "", err
76121
}
@@ -88,6 +133,9 @@ func EditFileTool(repoPath string) Tool {
88133
Description: "Edit a file by replacing oldString with newString.\nArgs: {\"path\": \"file.go\", \"oldString\": \"old\", \"newString\": \"new\"}",
89134
Execute: func(ctx context.Context, args map[string]string) (string, error) {
90135
path := filepath.Join(repoPath, args["path"])
136+
if isPathProtected(path) {
137+
return "", fmt.Errorf("edit %s is protected", args["path"])
138+
}
91139
oldStr := args["oldString"]
92140
newStr := args["newString"]
93141
if oldStr == "" {

0 commit comments

Comments
 (0)