Pii Leakage in Gorilla Mux
How PII Leakage Manifests in Gorilla Mux
PII leakage in Gorilla Mux applications typically occurs through improper handling of request data, inadequate validation of path parameters, and failure to sanitize query parameters. The router's flexible parameter extraction can inadvertently expose sensitive information if developers aren't careful about what data they log, return in error responses, or include in API responses.
One common pattern is using {param} in route definitions without proper validation. Consider this vulnerable endpoint:
r := mux.NewRouter()
r.HandleFunc("/users/{id}", func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
// Direct database query without validation
user, err := db.GetUserByID(id)
if err != nil {
http.Error(w, err.Error(), 500) // Leaks database error with PII
return
}
json.NewEncoder(w).Encode(user) // May expose sensitive fields
})("/users/{id}")This code has multiple PII leakage vectors: database errors might contain table names or query details, and the user struct could include fields like social security numbers, addresses, or financial data that shouldn't be exposed to unauthenticated users.
Another Gorilla Mux-specific issue arises with path parameter extraction. The router doesn't enforce type constraints by default:
r.HandleFunc("/accounts/{accountID}", func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
accountID := vars["accountID"]
// No validation that accountID is numeric
acc, err := db.GetAccount(accountID)
if err != nil {
http.Error(w, "Account not found", 404) // Generic error, but still problematic
}
json.NewEncoder(w).Encode(acc) // Full account object exposed
})("/accounts/{accountID}")An attacker could exploit this by requesting /accounts/1 OR 1=1 or similar injection attempts, potentially triggering database errors that leak schema information or causing the application to return data for accounts they shouldn't access.
Query parameter handling in Gorilla Mux also presents risks. The router's Request.URL.Query() returns all parameters without validation:
r.HandleFunc("/search", func(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query().Get("q")
// No sanitization of query parameter
results, err := db.SearchUsers(query)
if err != nil {
http.Error(w, err.Error(), 500) // Database error leakage
return
}
json.NewEncoder(w).Encode(results) // May include sensitive user data
})("/search")Without proper sanitization, this endpoint could return entire user profiles based on partial information, exposing PII to anyone who can guess or brute-force valid search terms.
Gorilla Mux-Specific Detection
Detecting PII leakage in Gorilla Mux applications requires examining both the routing configuration and the handler implementations. The first step is to audit your route definitions for overly permissive patterns.
Start by scanning your router configuration:
package main
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
)
func auditRoutes(router *mux.Router) {
// Walk through all registered routes
router.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
pathTemplate, err := route.GetPathTemplate()
if err != nil {
return err
}
fmt.Printf("Route: %s\n", pathTemplate)
// Check for problematic patterns
if strings.Contains(pathTemplate, "{id}") ||
strings.Contains(pathTemplate, "{user}") ||
strings.Contains(pathTemplate, "{email}") {
fmt.Printf(" WARNING: Route contains potentially sensitive parameter: %s\n", pathTemplate)
}
return nil
})
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/users/{id}", userHandler)
r.HandleFunc("/accounts/{accountID}", accountHandler)
auditRoutes(r)
}This audit helps identify routes that might be handling sensitive data. However, static analysis only catches obvious issues. For comprehensive detection, you need runtime scanning that tests actual API behavior.
This is where middleBrick provides unique value for Gorilla Mux applications. As a black-box scanner, it tests your running API endpoints without requiring source code access or credentials. middleBrick's PII leakage detection includes:
- Pattern matching for common PII formats (SSNs, credit card numbers, addresses, phone numbers)
- Testing for information disclosure in error responses
- Checking for excessive data exposure in successful responses
- Verifying authentication requirements for sensitive endpoints
- Testing for BOLA (Broken Object Level Authorization) vulnerabilities that could expose PII
To use middleBrick with your Gorilla Mux API:
# Install the CLI tool
npm install -g middlebrick
# Scan your API endpoint
middlebrick scan https://api.yourservice.com/users/123
# For CI/CD integration
middlebrick scan --threshold B --format json https://api.yourservice.com/ > report.jsonThe scanner runs 12 security checks in parallel, including specific PII detection patterns that would catch issues like returning full user profiles, leaking database errors with schema information, or exposing sensitive fields in API responses.
Gorilla Mux-Specific Remediation
Remediating PII leakage in Gorilla Mux applications requires a defense-in-depth approach. Start with input validation and sanitization using Gorilla Mux's built-in features.
For path parameter validation, use regular expression constraints in your route definitions:
r := mux.NewRouter()
// Only allow numeric IDs
r.HandleFunc("/users/{id:[0-9]+}", func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
// Now we know id is numeric - safe to use in database queries
user, err := db.GetUserByID(id)
if err != nil {
http.Error(w, "User not found", 404) // Generic error, no PII leakage
return
}
// Create a sanitized response struct
response := struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email,omitempty"`
}{
ID: user.ID,
Name: user.Name,
}
json.NewEncoder(w).Encode(response) // Only expose necessary fields
})("/users/{id:[0-9]+}")This approach prevents injection attacks through path parameters and ensures you only process valid input. The regex constraint [0-9]+ guarantees the ID is numeric before your handler code executes.
For query parameters, implement explicit validation and sanitization:
r.HandleFunc("/search", func(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query().Get("q")
// Validate and sanitize input
if query == "" || len(query) > 100 {
http.Error(w, "Invalid search query", 400)
return
}
// Sanitize to prevent injection
sanitizedQuery := sanitizeInput(query)
// Use parameterized queries to prevent SQL injection
results, err := db.SearchUsersWithLimit(sanitizedQuery, 10)
if err != nil {
http.Error(w, "Search failed", 500) // Generic error
return
}
// Create sanitized response
var sanitizedResults []struct {
ID string `json:"id"`
Name string `json:"name"`
}
for _, user := range results {
sanitizedResults = append(sanitizedResults, struct {
ID string `json:"id"`
Name string `json:"name"`
}{
ID: user.ID,
Name: user.Name,
})
}
json.NewEncoder(w).Encode(sanitizedResults)
})("/search")The key improvements here are input validation (length check), sanitization function, parameterized database queries, and creating a response struct that only includes necessary fields.
For comprehensive PII protection, implement middleware that automatically sanitizes responses:
type piiSanitizer struct {
next http.Handler
}
func (ps *piiSanitizer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Create a buffer to capture the response
rec := httptest.NewRecorder()
ps.next.ServeHTTP(rec, r)
// Read the response body
body := rec.Body.Bytes()
// Check if it's JSON
var data map[string]interface{}
if json.Unmarshal(body, &data) == nil {
// Sanitize the data structure
sanitized := sanitizePII(data)
// Write the sanitized response
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(sanitized)
} else {
// Non-JSON response, write as-is
w.WriteHeader(rec.Code)
w.Write(body)
}
}
func sanitizePII(data map[string]interface{}) map[string]interface{} {
sanitized := make(map[string]interface{})
for key, value := range data {
switch key {
case "ssn", "social_security_number", "credit_card", "cvv":
// Remove or mask sensitive fields
sanitized[key] = "[REDACTED]"
case "email", "phone":
// Allow some fields but consider if they should be exposed
sanitized[key] = value
default:
sanitized[key] = value
}
}
return sanitized
}
// Use the middleware
r.Use(func(next http.Handler) http.Handler {
return &piiSanitizer{next: next}
})This middleware automatically scans all JSON responses and removes or masks sensitive fields before they're sent to the client.
For production deployment, integrate middleBrick into your CI/CD pipeline to catch PII leakage before deployment:
# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run middleBrick Scan
run: |
npm install -g middlebrick
middlebrick scan --threshold B --format json https://staging.yourservice.com/ > middlebrick-report.json
- name: Fail on high risk
run: |
SCORE=$(jq '.score' middlebrick-report.json)
if [ $SCORE -lt 80 ]; then
echo "Security score below threshold: $SCORE"
exit 1
fiThis ensures that any PII leakage vulnerabilities are caught automatically during development, preventing them from reaching production.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |
Frequently Asked Questions
How does Gorilla Mux's path parameter handling differ from other Go routers regarding PII leakage?
mux.Vars(r), but unlike some routers that enforce strict typing, it returns all parameters as strings without validation. This means you must explicitly validate and sanitize parameters in your handlers. The router also doesn't provide built-in PII detection or automatic field filtering, so developers must implement their own security measures to prevent sensitive data exposure.