Regex Dos in Chi with Api Keys
Regex Dos in Chi with Api Keys — how this specific combination creates or exposes the vulnerability
A Regular Expression Denial of Service (Regex DoS) occurs when a poorly designed regular expression exhibits catastrophic backtracking on certain inputs, causing exponential time consumption. In Chi, a lightweight HTTP router for Go, this risk is particularly relevant when developers use regex patterns to match route paths or extract parameters that include API key-like segments (e.g., keys embedded in URLs or header values).
Chi routes can include route parameters, and it is common to use regex constraints to validate or capture values. For example, a route intended to capture an API key might define a pattern like ^{[a-zA-Z0-9]{32}}$ to enforce a 32-character alphanumeric key. While this pattern appears safe, adjacent optional groups or repeated quantifiers—such as (a+)+ or patterns with nested quantifiers like ([a-zA-Z0-9]*)*—can cause catastrophic backtracking when presented with specially crafted strings.
An attacker can send a request with a long, repetitive string that matches the prefix of the regex but fails later in the pattern, forcing the engine to explore an exponential number of paths. For instance, a route defined as Route().Get("/key/{id:^([a-zA-Z0-9]*){2,20}$}", handler) is vulnerable because the quantifier {2,20} applied to a repeated character class creates conditions for backtracking explosions when the input length grows or contains ambiguous characters.
Chi does not inherently protect against malformed regex patterns; it relies on the developer to write non-exponential expressions. When API keys are extracted via regex in routes or middleware, an attacker can probe endpoints with crafted payloads that trigger excessive CPU consumption, leading to service degradation without requiring authentication or knowledge of valid keys.
Because middleBrick scans unauthenticated attack surfaces, it can detect routes with complex regex constraints on parameters that resemble key formats and flag them as potential Regex DoS surfaces. This is part of its broader input validation and property authorization checks, which analyze endpoint definitions and runtime behavior for risky patterns without needing credentials.
To mitigate this in Chi, avoid nesting quantifiers and ensure quantified groups are not overlapping. Prefer exact or bounded quantifiers, and validate API keys using simple equality checks or hash lookups rather than complex regexes in routing logic. middleBrick’s findings include specific remediation guidance to help developers replace dangerous patterns with safer alternatives.
Api Keys-Specific Remediation in Chi — concrete code fixes
Securing API key handling in Chi involves avoiding regex-based extraction and validation, and instead using explicit parameter capture and constant-time comparison. Below are concrete, safe patterns for managing API keys in Chi routes and middleware.
1. Use Chi’s built-in route parameters instead of regex constraints
Define a static segment for the key path or use a simple parameter without regex constraints. Validate the key in middleware or handler logic using direct comparison or a secure lookup.
import (
"net/http"
"github.com/go-chi/chi/v5"
)
// Safe: capture key as a plain parameter, validate in middleware
func APIKeyMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
key := chi.URLParam(r, "key")
if !isValidAPIKey(key) {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
func isValidAPIKey(key string) bool {
// Use a constant-time comparison to avoid timing attacks
expected := "abc123..." // retrieve securely, e.g., from a vault
return subtle.ConstantTimeCompare([]byte(key), []byte(expected)) == 1
}
func main() {
r := chi.NewRouter()
r.Use(APIKeyMiddleware)
// Static segment; key is not part of the route pattern
r.Get("/resource/{key}", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("ok"))
})
http.ListenAndServe(":8080", r)
}
2. Avoid regex in route definitions for key validation
Do not embed regex quantifiers or complex patterns in Chi route definitions when they involve API keys. Instead, extract the key and validate it programmatically.
import (
"net/http"
"github.com/go-chi/chi/v5"
)
// Unsafe pattern to avoid:
// r.Get("/key/{id:^([a-zA-Z0-9]*){2,20}$}", handler)
// Safe alternative
r.Get("/key/{id}", func(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
if !isWellFormedKey(id) {
http.Error(w, "bad request", http.StatusBadRequest)
return
}
// proceed safely
w.Write([]byte("valid"))
})
func isWellFormedKey(key string) bool {
// Simple length and character checks without regex
if len(key) != 32 {
return false
}
for _, ch := range key {
if !(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ('0' <= ch && ch <= '9')) {
return false
}
}
return true
}
3. Secure middleware and header-based API keys
When API keys are passed in headers, avoid parsing with regex. Use standard header access and validation functions.
import (
"net/http"
"github.com/go-chi/chi/v5"
)
func HeaderAPIKeyMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
key := r.Header.Get("X-API-Key")
if key == "" || !isValidHeaderKey(key) {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}
func isValidHeaderKey(key string) bool {
// Example: enforce format without regex
// e.g., 8 hyphen-separated groups of 4 hex digits
if len(key) != 36 {
return false
}
// Further checks can be added safely
return true
}
func main() {
r := chi.NewRouter()
r.Use(HeaderAPIKeyMiddleware)
r.Get("/secure", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("secure data"))
})
http.ListenAndServe(":8080", r)
}
These approaches eliminate regex-related DoS risks by removing complex quantifiers from route definitions and validating API keys through controlled, linear checks. middleBrick’s scans can highlight routes with regex constraints on key-like parameters and recommend such safer patterns as part of its input validation findings.
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 |