Skip to content

Commit c651cc3

Browse files
committed
Documentation updates by copilot
1 parent 2cd1d2f commit c651cc3

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

go/ql/src/Security/CWE-022/TaintedPath.qhelp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,20 @@ result in the string "../" if only "../" sequences are removed.
3838
Finally, the simplest (but most restrictive) option is to use an allow list of safe patterns
3939
and make sure that the user input matches one of these patterns.
4040
</p>
41+
42+
<p>
43+
<b>Sanitizer functions from the Go standard library:</b>
44+
</p>
45+
<p>
46+
The Go standard library provides several functions that can help sanitize paths:
47+
</p>
48+
<ul>
49+
<li><code>filepath.Rel(basepath, targpath)</code> - Returns a relative path from basepath to targpath. If the path is not contained within basepath, it returns an error, making it useful for validating that a path stays within expected boundaries.</li>
50+
<li><code>filepath.Clean(path)</code> - When used with a path that starts with "/" (e.g., <code>filepath.Clean("/" + userPath)</code>), it normalizes the path and can help prevent path traversal by resolving ".." sequences.</li>
51+
<li><code>filepath.IsLocal(path)</code> - Returns true if the path is local (doesn't start with "/" and doesn't contain ".."), making it useful for validating relative paths.</li>
52+
<li><code>strings.Contains(path, "..")</code> - Can be used to detect path traversal sequences in user input.</li>
53+
<li><code>strings.HasPrefix(path, safePrefix)</code> - Can be used to ensure paths start with expected safe prefixes.</li>
54+
</ul>
4155
</recommendation>
4256

4357
<example>
@@ -71,6 +85,13 @@ that the resulting path is still within it.
7185
</p>
7286
<sample src="TaintedPathGood2.go" />
7387
<p>
88+
<b>Using Go standard library sanitizers:</b>
89+
</p>
90+
<p>
91+
You can also use Go's built-in path validation functions for additional safety:
92+
</p>
93+
<sample src="TaintedPathSanitizers.go" />
94+
<p>
7495
Note that <code>/home/user</code> is just an example, you should replace it with the actual
7596
safe directory in your application. Also, while in this example the path of the safe
7697
directory is absolute, this may not always be the case, and you may need to resolve it
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package main
2+
3+
import (
4+
"net/http"
5+
"os"
6+
"path/filepath"
7+
"strings"
8+
)
9+
10+
func handleFileWithSanitizers(w http.ResponseWriter, r *http.Request) {
11+
userPath := r.URL.Query().Get("file")
12+
safeDir := "/home/user/documents"
13+
14+
// Method 1: Using filepath.IsLocal to validate the path is local
15+
if !filepath.IsLocal(userPath) {
16+
http.Error(w, "Invalid path: must be local", http.StatusBadRequest)
17+
return
18+
}
19+
20+
// Method 2: Using strings.Contains to check for path traversal sequences
21+
if strings.Contains(userPath, "..") {
22+
http.Error(w, "Invalid path: contains path traversal", http.StatusBadRequest)
23+
return
24+
}
25+
26+
// Method 3: Using filepath.Rel to ensure path is within safe directory
27+
relPath, err := filepath.Rel(safeDir, filepath.Join(safeDir, userPath))
28+
if err != nil || strings.HasPrefix(relPath, "..") {
29+
http.Error(w, "Invalid path: outside safe directory", http.StatusBadRequest)
30+
return
31+
}
32+
33+
// Method 4: Using filepath.Clean with absolute prefix for normalization
34+
cleanPath := filepath.Clean("/" + userPath)
35+
if strings.Contains(cleanPath, "..") {
36+
http.Error(w, "Invalid path after normalization", http.StatusBadRequest)
37+
return
38+
}
39+
40+
// Method 5: Using strings.HasPrefix for additional validation
41+
finalPath := filepath.Join(safeDir, userPath)
42+
if !strings.HasPrefix(finalPath, safeDir) {
43+
http.Error(w, "Invalid path: must be within safe directory", http.StatusBadRequest)
44+
return
45+
}
46+
47+
// Safe to open file
48+
file, err := os.Open(finalPath)
49+
if err != nil {
50+
http.Error(w, "File not found", http.StatusNotFound)
51+
return
52+
}
53+
defer file.Close()
54+
55+
// Process file...
56+
}
57+
58+
// Example using mime/multipart filename sanitization
59+
func handleUpload(w http.ResponseWriter, r *http.Request) {
60+
err := r.ParseMultipartForm(32 << 20) // 32MB max
61+
if err != nil {
62+
http.Error(w, err.Error(), http.StatusBadRequest)
63+
return
64+
}
65+
66+
file, header, err := r.FormFile("upload")
67+
if err != nil {
68+
http.Error(w, err.Error(), http.StatusBadRequest)
69+
return
70+
}
71+
defer file.Close()
72+
73+
// The Filename field is automatically sanitized by mime/multipart
74+
// using filepath.Base, making it safe from path traversal
75+
filename := header.Filename
76+
77+
// Additional validation can still be useful
78+
if strings.Contains(filename, "..") || strings.ContainsAny(filename, "/\\") {
79+
http.Error(w, "Invalid filename", http.StatusBadRequest)
80+
return
81+
}
82+
83+
// Safe to use filename
84+
_ = filename
85+
}

0 commit comments

Comments
 (0)