返回 DeepSeek-Reasonix
write_paths.go
根目录 / internal / shellsafe / write_paths.go
1 package shellsafe
2
3 import (
4 "mvdan.cc/sh/v3/syntax"
5 "reasonix/internal/shellparse"
6 "strings"
7 )
8
9 // StaticWritePaths proves the complete write surface of a deliberately small
10 // shell subset. Directory permissions and model-provided scopes are never
11 // evidence of the actual command's targets. Unrecognized forms stay opaque.
12 func StaticWritePaths(command string) ([]string, bool) {
13 f, err := shellparse.ParseBash(command)
14 if err != nil || len(f.Stmts) != 1 {
15 return nil, false
16 }
17 s := f.Stmts[0]
18 if s.Background || s.Coprocess || s.Disown || s.Negated {
19 return nil, false
20 }
21 c, ok := s.Cmd.(*syntax.CallExpr)
22 if !ok || len(c.Assigns) > 0 || len(c.Args) == 0 || len(s.Redirs) == 0 {
23 return nil, false
24 }
25 name, ok := shellparse.StaticWord(c.Args[0])
26 if !ok || (name != "echo" && name != "printf") {
27 return nil, false
28 }
29 for _, arg := range c.Args {
30 if _, ok := shellparse.StaticWord(arg); !ok {
31 return nil, false
32 }
33 }
34 var paths []string
35 for _, r := range s.Redirs {
36 if r.Op != syntax.RdrOut && r.Op != syntax.AppOut {
37 return nil, false
38 }
39 path, ok := shellparse.StaticWord(r.Word)
40 if !ok || path == "" || strings.ContainsAny(path, "*?[{~") {
41 return nil, false
42 }
43 paths = append(paths, path)
44 }
45 return paths, true
46 }
47
47 lines GO