diff --git a/go/ql/src/Security/CWE-022/TaintedPath.qhelp b/go/ql/src/Security/CWE-022/TaintedPath.qhelp index 94edec4e4f4b..ab9b3be41158 100644 --- a/go/ql/src/Security/CWE-022/TaintedPath.qhelp +++ b/go/ql/src/Security/CWE-022/TaintedPath.qhelp @@ -38,6 +38,20 @@ result in the string "../" if only "../" sequences are removed. Finally, the simplest (but most restrictive) option is to use an allow list of safe patterns and make sure that the user input matches one of these patterns.
+ ++Sanitizer functions from the Go standard library: +
++The Go standard library provides several functions that can help sanitize paths: +
+filepath.Rel(basepath, targpath)
- 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.filepath.Clean(path)
- When used with a path that starts with "/" (e.g., filepath.Clean("/" + userPath)
), it normalizes the path and can help prevent path traversal by resolving ".." sequences.filepath.IsLocal(path)
- Returns true if the path is local (doesn't start with "/" and doesn't contain ".."), making it useful for validating relative paths.strings.Contains(path, "..")
- Can be used to detect path traversal sequences in user input.strings.HasPrefix(path, safePrefix)
- Can be used to ensure paths start with expected safe prefixes.+Using Go standard library sanitizers: +
++You can also use Go's built-in path validation functions for additional safety: +
+
Note that /home/user
is just an example, you should replace it with the actual
safe directory in your application. Also, while in this example the path of the safe
directory is absolute, this may not always be the case, and you may need to resolve it
diff --git a/go/ql/src/Security/CWE-022/TaintedPathSanitizers.go b/go/ql/src/Security/CWE-022/TaintedPathSanitizers.go
new file mode 100644
index 000000000000..6c2696911a08
--- /dev/null
+++ b/go/ql/src/Security/CWE-022/TaintedPathSanitizers.go
@@ -0,0 +1,56 @@
+package main
+
+import (
+ "net/http"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+func handleFileWithSanitizers(w http.ResponseWriter, r *http.Request) {
+ userPath := r.URL.Query().Get("file")
+ safeDir := "/home/user/documents"
+
+ // Method 1: Using filepath.IsLocal to validate the path is local
+ if !filepath.IsLocal(userPath) {
+ http.Error(w, "Invalid path: must be local", http.StatusBadRequest)
+ return
+ }
+
+ // Method 2: Using strings.Contains to check for path traversal sequences
+ if strings.Contains(userPath, "..") {
+ http.Error(w, "Invalid path: contains path traversal", http.StatusBadRequest)
+ return
+ }
+
+ // Method 3: Using filepath.Rel to ensure path is within safe directory
+ relPath, err := filepath.Rel(safeDir, filepath.Join(safeDir, userPath))
+ if err != nil || strings.HasPrefix(relPath, "..") {
+ http.Error(w, "Invalid path: outside safe directory", http.StatusBadRequest)
+ return
+ }
+
+ // Method 4: Using filepath.Clean with absolute prefix for normalization
+ cleanPath := filepath.Clean("/" + userPath)
+ if strings.Contains(cleanPath, "..") {
+ http.Error(w, "Invalid path after normalization", http.StatusBadRequest)
+ return
+ }
+
+ // Method 5: Using strings.HasPrefix for additional validation
+ finalPath := filepath.Join(safeDir, userPath)
+ if !strings.HasPrefix(finalPath, safeDir) {
+ http.Error(w, "Invalid path: must be within safe directory", http.StatusBadRequest)
+ return
+ }
+
+ // Safe to open file
+ file, err := os.Open(finalPath)
+ if err != nil {
+ http.Error(w, "File not found", http.StatusNotFound)
+ return
+ }
+ defer file.Close()
+
+ // Process file...
+}