MCPcopy
hub / github.com/wavetermdev/waveterm / validateTextFile

Function validateTextFile

pkg/aiusechat/tools_writefile.go:20–75  ·  view source on GitHub ↗

100KB

(expandedPath string, verb string, mustExist bool)

Source from the content-addressed store, hash-verified

18const MaxEditFileSize = 100 * 1024 // 100KB
19
20func validateTextFile(expandedPath string, verb string, mustExist bool) (os.FileInfo, error) {
21 if blocked, reason := isBlockedFile(expandedPath); blocked {
22 return nil, fmt.Errorf("access denied: potentially sensitive file: %s", reason)
23 }
24
25 fileInfo, err := os.Lstat(expandedPath)
26 if err != nil {
27 if os.IsNotExist(err) {
28 if mustExist {
29 return nil, fmt.Errorf("file does not exist: %s", expandedPath)
30 }
31 return nil, nil
32 }
33 return nil, fmt.Errorf("failed to stat file: %w", err)
34 }
35
36 if fileInfo.Mode()&os.ModeSymlink != 0 {
37 target, _ := os.Readlink(expandedPath)
38 if target == "" {
39 target = "(unknown)"
40 }
41 return nil, fmt.Errorf("cannot %s symlinks (target: %s). %s the target file directly if needed", verb, utilfn.MarshalJSONString(target), verb)
42 }
43
44 if fileInfo.IsDir() {
45 return nil, fmt.Errorf("path is a directory, cannot %s it", verb)
46 }
47
48 if !fileInfo.Mode().IsRegular() {
49 return nil, fmt.Errorf("path is not a regular file (devices, pipes, sockets not supported)")
50 }
51
52 if fileInfo.Size() > MaxEditFileSize {
53 return nil, fmt.Errorf("file is too large (%d bytes, max %d bytes)", fileInfo.Size(), MaxEditFileSize)
54 }
55
56 fileData, err := os.ReadFile(expandedPath)
57 if err != nil {
58 return nil, fmt.Errorf("failed to read file: %w", err)
59 }
60
61 if utilfn.HasBinaryData(fileData) {
62 return nil, fmt.Errorf("file appears to contain binary data")
63 }
64
65 dirPath := filepath.Dir(expandedPath)
66 dirInfo, err := os.Stat(dirPath)
67 if err != nil && !os.IsNotExist(err) {
68 return nil, fmt.Errorf("failed to stat directory: %w", err)
69 }
70 if err == nil && dirInfo.Mode().Perm()&0222 == 0 {
71 return nil, fmt.Errorf("directory is not writable (no write permission)")
72 }
73
74 return fileInfo, nil
75}
76
77type writeTextFileParams struct {

Callers 7

verifyWriteTextFileInputFunction · 0.85
writeTextFileCallbackFunction · 0.85
verifyEditTextFileInputFunction · 0.85
EditTextFileDryRunFunction · 0.85
editTextFileCallbackFunction · 0.85
deleteTextFileCallbackFunction · 0.85

Calls 8

MarshalJSONStringFunction · 0.92
HasBinaryDataFunction · 0.92
isBlockedFileFunction · 0.85
ModeMethod · 0.80
ReadFileMethod · 0.80
StatMethod · 0.80
IsDirMethod · 0.45
SizeMethod · 0.45

Tested by

no test coverage detected