Out Of Bounds Write in Gorilla Mux
How Out Of Bounds Write Manifests in Gorilla Mux
Out Of Bounds Write (OOBW) vulnerabilities in Gorilla Mux applications typically occur when path parameters or URL segments are used to access array elements or slice indices without proper validation. Gorilla Mux's powerful routing capabilities, while convenient, can inadvertently create attack surfaces if parameters are directly used as array indices.
Consider this common Gorilla Mux pattern:
router := mux.NewRouter()
router.HandleFunc("/items/{id}", getItemById)
func getItemById(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
// DANGEROUS: id is a string from URL, but used as array index
items := []string{"item1", "item2", "item3"}
idx, _ := strconv.Atoi(id)
if idx < len(items) {
fmt.Fprintf(w, items[idx])
}
}
This code has multiple OOBW vulnerabilities:
- The
idparameter comes directly from the URL without validation - No bounds checking ensures
idxis withinitemsarray range - Negative values or extremely large numbers can cause undefined behavior
A more subtle Gorilla Mux OOBW occurs with slice operations:
router.HandleFunc("/items/range/{start}/{end}", getItemsRange)
func getItemsRange(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
start, _ := strconv.Atoi(vars["start"])
end, _ := strconv.Atoi(vars["end"])
items := getAllItems() // returns []Item
// OOBW: no validation of start/end against items length
subset := items[start:end]
json.NewEncoder(w).Encode(subset)
}
This slice operation can panic if start or end exceed array bounds, or if start > end. Gorilla Mux's strict routing means these parameters will always be present (if the route matches), but their values remain untrusted.
Another Gorilla Mux-specific pattern involves using parameters to access map keys that reference arrays:
router.HandleFunc("/users/{userId}/permissions/{permIndex}", getUserPermission)
func getUserPermission(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
userId := vars["userId"]
permIndex := vars["permIndex"]
userPerms := getUserPermissions(userId) // map[string][]string
// OOBW: permIndex used directly without validation
permissions := userPerms[userId]
idx, _ := strconv.Atoi(permIndex)
if idx < len(permissions) {
fmt.Fprintf(w, permissions[idx])
}
}
The combination of Gorilla Mux's flexible parameter extraction and Go's zero-based indexing creates a perfect storm for OOBW when parameters are used as indices without validation.
Gorilla Mux-Specific Detection
Detecting OOBW vulnerabilities in Gorilla Mux applications requires both static analysis of routing patterns and dynamic testing of parameter handling. middleBrick's black-box scanning approach is particularly effective for this, as it tests the actual runtime behavior of your API endpoints.
middleBrick specifically scans for Gorilla Mux OOBW patterns by:
- Testing path parameters with boundary values (0, -1, max int, extremely large numbers)
- Analyzing route definitions to identify parameter patterns that could be used as indices
- Checking for unvalidated parameter usage in array/slice operations
- Looking for slice operations that could panic with invalid indices
When middleBrick detects potential OOBW issues, it provides specific findings like:
Finding: Potential Out Of Bounds Write in /items/{id}
Severity: High
Category: Input Validation
Remediation: Validate and sanitize path parameters before using as array indices
Details:
- Route: /items/{id}
- Parameter: id (used as array index without validation)
- Risk: Array index out of bounds could cause panic or information disclosure
For comprehensive testing, you can also use middleBrick's CLI to scan your Gorilla Mux API:
# Scan a running Gorilla Mux API
middlebrick scan https://api.example.com --api-name "My Gorilla App"
# Scan with specific focus on input validation
middlebrick scan https://api.example.com --focus "input-validation"
The GitHub Action integration allows continuous OOBW detection in your CI/CD pipeline:
name: API Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run middleBrick Scan
uses: middlebrick/middlebrick-action@v1
with:
target_url: http://localhost:8080
fail_below_score: 80
token: ${{ secrets.MIDDLEBRICK_TOKEN }}
middleBrick's LLM security scanning is also relevant for Gorilla Mux applications that serve AI endpoints, as OOBW vulnerabilities in prompt processing or token handling can be particularly dangerous.
Gorilla Mux-Specific Remediation
Remediating OOBW vulnerabilities in Gorilla Mux requires implementing proper input validation and safe array access patterns. Here are Gorilla Mux-specific remediation strategies:
1. Always validate path parameters before using as indices:
router.HandleFunc("/items/{id}", getItemById)
func getItemById(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
idStr := vars["id"]
id, err := strconv.Atoi(idStr)
if err != nil || id < 0 {
http.Error(w, "Invalid item ID", http.StatusBadRequest)
return
}
items := getItems()
if id >= len(items) {
http.Error(w, "Item not found", http.StatusNotFound)
return
}
fmt.Fprintf(w, items[id])
}
2. Use Gorilla Mux's built-in constraints for safer routing:
// Constrain id to positive integers only
router.HandleFunc("/items/{id:[0-9]+}", getItemById)
// Even better: constrain to reasonable range
router.HandleFunc("/items/{id:[1-9][0-9]?}", getItemById)
// For slice ranges with validation
router.HandleFunc("/items/range/{start:[0-9]+}/{end:[0-9]+}", getItemsRange)
3. Implement safe slice operations with bounds checking:
func getItemsRange(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
start, err1 := strconv.Atoi(vars["start"])
end, err2 := strconv.Atoi(vars["end"])
if err1 != nil || err2 != nil || start < 0 || end < start {
http.Error(w, "Invalid range parameters", http.StatusBadRequest)
return
}
items := getAllItems()
if start >= len(items) {
http.Error(w, "Start index out of range", http.StatusNotFound)
return
}
// Safe slice: Go handles end > len(items) gracefully
if end > len(items) {
end = len(items)
}
subset := items[start:end]
json.NewEncoder(w).Encode(subset)
}
4. Use helper functions for consistent validation:
func validateArrayIndex(param string, max int) (int, error) {
idx, err := strconv.Atoi(param)
if err != nil || idx < 0 || idx >= max {
return 0, fmt.Errorf("index out of valid range [0, %d)", max)
}
return idx, nil
}
func getItemById(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
items := getItems()
idx, err := validateArrayIndex(vars["id"], len(items))
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
fmt.Fprintf(w, items[idx])
}
5. For map-based access patterns:
func getUserPermission(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
userId := vars["userId"]
permIndexStr := vars["permIndex"]
userPerms, exists := getUserPermissions(userId)
if !exists {
http.Error(w, "User not found", http.StatusNotFound)
return
}
permIndex, err := validateArrayIndex(permIndexStr, len(userPerms))
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
fmt.Fprintf(w, userPerms[permIndex])
}
6. Consider using middleware for parameter validation:
func validateIndexParam(paramName string, max int) mux.MiddlewareFunc {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
param := vars[paramName]
if _, err := validateArrayIndex(param, max); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
next.ServeHTTP(w, r)
})
}
}
// Usage
router.Handle("/items/{id:[0-9]+}\