Path Traversal in Gorilla Mux with Mongodb
Path Traversal in Gorilla Mux with Mongodb — how this specific combination creates or exposes the vulnerability
A path traversal risk arises in a Gorilla Mux route when user-controlled path components are used to build filesystem paths or to construct database queries without strict validation. While Gorilla Mux handles HTTP routing and parameter extraction, the vulnerability typically occurs in application logic that maps URL parameters to filesystem operations or to document lookup keys in Mongodb. For example, if a route like /files/{filename} takes vars["filename"] and appends it to a base directory, an attacker can supply sequences such as ../../../etc/passwd to traverse directories. With Mongodb, traversal can also mean unintended document access when an identifier is derived from user input and used in a query without canonicalization or strict type checks.
Consider a handler that serves user documents by ID while also exposing a file route:
func docHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
docID := vars["id"]
// Unsafe: directly use user input in a Mongodb query
filter := bson.M{"_id": docID}
var result bson.M
if err := collection.FindOne(context.TODO(), filter).Decode(&result); err != nil {
http.Error(w, "not found", http.StatusNotFound)
return
}
w.Write(result["content"])
}
If docID is not validated, an attacker might supply ../../users/admin (string-based traversal) or a specially crafted ObjectId that leads to unauthorized reads. With filesystem interactions, a request to /files/../../../etc/passwd could return sensitive system files when the server concatenates paths naively:
func fileHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
filename := vars["filename"]
// Unsafe path join
path := filepath.Join("/var/data/uploads", filename)
http.ServeFile(w, r, path)
}
Even when using ObjectId for Mongodb, supplying a non-ObjectId string can bypass expected scoping if the query is not strict, effectively performing an unintended traversal across logical data boundaries. The risk is compounded when authorization checks are missing or applied after the lookup, allowing horizontal or vertical privilege escalation across user data or system files.
middleBrick detects such patterns during unauthenticated scans by analyzing OpenAPI specs and runtime behavior, flagging endpoints where path parameters flow into filesystem or database operations without strict validation or sanitization.
Mongodb-Specific Remediation in Gorilla Mux — concrete code fixes
Remediation focuses on strict input validation, canonicalization, and avoiding direct concatenation of user input into filesystem paths or query keys. For filesystem access, resolve paths to a canonical absolute location and ensure the resolved path remains within the intended directory. For Mongodb, use well-typed identifiers and avoid string-based selectors when possible; validate ObjectId format and scope queries with additional filters such as tenant or user ownership.
Secure file handler example
func safeFileHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
filename := vars["filename"]
// Restrict to a safe basename to prevent directory components
base := filepath.Base(filename)
if base == "." || base == "" {
http.Error(w, "invalid file", http.StatusBadRequest)
return
}
// Ensure the resolved path stays inside the allowed directory
root := "/var/data/uploads"
path := filepath.Join(root, base)
if !strings.HasPrefix(path, filepath.Clean(root)+string(os.PathSeparator)) && path != filepath.Clean(root) {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
http.ServeFile(w, r, path)
}
Secure Mongodb handler with ObjectId validation and ownership scope
type Document struct {
ID primitive.ObjectID `bson:"_id"`
UserID string `bson:"user_id"`
Filename string `bson:"filename"`
Content string `bson:"content"`
}
func getDocumentHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
userID := r.Header.Get("X-User-ID") // Assume authenticated user ID is provided by auth layer
// Validate ObjectId format
if !primitive.IsValidObjectID(vars["id"]) {
http.Error(w, "invalid document id", http.StatusBadRequest)
return
}
objID := primitive.ObjectIDFromHex(vars["id"])
// Scope query by both ID and user ownership to prevent traversal across users
filter := bson.M{
"_id": objID,
"user_id": userID,
}
var doc Document
if err := collection.FindOne(context.TODO(), filter).Decode(&doc); err != nil {
http.Error(w, "not found", http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/octet-stream")
w.Write([]byte(doc.Content))
}
Additional practices
- Use allowlists for filenames and reject characters such as path separators, dot-dot sequences, and control characters.
- For ObjectId, prefer using primitive.ObjectIDFromHex with format validation rather than raw string passes to queries.
- Apply defense in depth: enforce authentication and authorization checks before data access, and log suspicious traversal attempts.
- In specs, describe parameter constraints explicitly (pattern, enum) so automated tools and clients can validate inputs.
middleBrick’s CLI can be used to verify that such endpoints are properly constrained; running middlebrick scan <url> will report findings related to input validation and authorization boundaries.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |