Regex Dos in Actix with Basic Auth
Regex Dos in Actix with Basic Auth — how this specific combination creates or exposes the vulnerability
Regex Denial of Service (Regex Dos) occurs when an attacker supplies input that causes a regular expression to exhibit catastrophic backtracking, consuming excessive CPU time and degrading service. In Actix web applications, enabling HTTP Basic Auth at the framework level can inadvertently amplify this risk when regex-based validation is applied to the Authorization header or to user-controlled data derived from it.
Consider an Actix app that uses a guard or middleware to inspect or transform the Authorization header using a custom regex. A common pattern is to extract the username or scope from a bearer-like token or to validate credentials with a pattern such as ^(?:[a-zA-Z0-9._%-]+:[a-zA-Z0-9._%-]+)?$. If the regex is poorly constructed—using nested quantifiers on overlapping character classes—and the framework processes repeated or malformed header values, an attacker can send crafted inputs that cause the regex engine to backtrack exponentially. Because Actix may evaluate these checks before routing to handlers, the CPU cost is incurred on every request, leading to elevated latency or denial of service even before business logic runs.
When combined with Basic Auth, the attack surface changes in two ways. First, the Authorization header is base64-encoded but easily decoded and replayed; an attacker can send many variations of usernames and passwords to probe regex behavior if validation logic is applied post-decoding. Second, if the application uses regex to validate or parse credentials (e.g., enforcing format rules on the username or password), the repeated decoding and matching can compound the backtracking cost. This is particularly relevant when the regex includes optional groups or alternations that interact poorly with common character sequences found in encoded credentials.
In an OpenAPI/Swagger context, regex constraints defined in schemas for security schemes (e.g., securitySchemes with type: http and scheme: basic) are typically not executed by the scanner; instead, middleBrick cross-references runtime behavior with spec definitions. If your Actix service declares Basic Auth in the spec but implements additional regex validation in code, the scan can surface mismatches and risky patterns. Findings from such checks map to the OWASP API Top 10 category 2023-A05: Security Misconfiguration and can align with compliance frameworks like PCI-DSS and SOC2 when authentication controls are involved.
Real-world patterns observed in the wild include regexes like ^(a+)+$-style constructs applied to header values or user input derived from them, which are notorious for catastrophic backtracking. In Actix, middleware or guards that apply such patterns on every request—especially when Basic Auth is in play—should be reviewed for quantifier misuse, overlapping classes, and lack of atomic grouping or possessive quantifiers where the engine supports them.
To detect these issues, middleBrick runs parallel security checks including Input Validation and Property Authorization. During an unauthenticated scan, the tool probes endpoints, inspects the OpenAPI spec for Basic Auth declarations, and analyzes runtime responses for signs of inefficient regex processing. While middleBrick does not fix the regex, it provides prioritized findings with severity, reproduction steps, and remediation guidance to help developers refactor patterns safely.
Basic Auth-Specific Remediation in Actix — concrete code fixes
Remediation focuses on removing or simplifying regex patterns applied to Authorization header values and ensuring validation logic does not introduce backtracking risks. When Basic Auth is required, prefer framework-provided parsers or well-audited crates instead of custom regex. Below are concrete Actix examples demonstrating secure approaches.
Example 1: Using Actix's built-in Basic Auth extractor
Actix-web provides actix_web::http::HeaderValue utilities and the actix_http::header::authorization::Basic type to parse credentials without regex. This avoids backtracking-prone pattern matching on the header string.
use actix_web::{web, HttpRequest, HttpResponse};
use actix_http::header::authorization::Basic;
use actix_web::http::Header;
async fn handler(req: HttpRequest) -> HttpResponse {
if let Some(auth) = req.headers().typed_get::() {
let username = auth.user_id();
let password = auth.password().unwrap_or("");
// Perform safe credential checks here, e.g., constant-time comparison
if validate_credentials(username, password) {
return HttpResponse::Ok().finish();
}
}
HttpResponse::Unauthorized()
.insert_header((actix_web::http::header::WWW_AUTHENTICATE, "Basic realm=\"api\""))
.finish()
}
fn validate_credentials(user: &str, pass: &str) -> bool {
// Use constant-time comparison and avoid regex on user input
user == "admin" && pass == "s3cr3t"
}
Example 2: Avoiding regex on Authorization header values
If you must inspect raw header values, use simple string operations instead of regex. For example, check the scheme prefix and decode base64 without complex patterns.
use base64::Engine;
use actix_web::HttpRequest;
fn parse_basic_header_raw(header_value: &str) -> Option<(String, String)> {
// Simple prefix check and split, no regex
if let Some(stripped) = header_value.strip_prefix("Basic ") {
let decoded = base64::engine::general_purpose::STANDARD.decode(stripped.as_bytes()).ok()?;
let creds = String::from_utf8(decoded).ok()?;
let mut parts = creds.splitn(2, ':');
let user = parts.next()?.to_string();
let pass = parts.next()?.to_string();
Some((user, pass))
} else {
None
}
}
async fn login_handler(req: HttpRequest) -> HttpResponse {
match req.headers().get("authorization") {
Some(hv) => {
if let Some((user, pass)) = parse_basic_header_raw(hv.to_str().unwrap_or("")) {
if user == "admin" && pass == "secret" {
return HttpResponse::Ok().finish();
}
}
HttpResponse::Unauthorized().finish()
}
None => HttpResponse::BadRequest().finish(),
}
}
Example 3: If regex is unavoidable, make it safe
When regex is necessary, avoid nested quantifiers and ensure linear runtime. Use non-backtracking constructs where possible (e.g., [^:]+ instead of .*), and anchor patterns tightly. Prefer the regex crate with regex-automata in non-backtracking mode for critical checks.
use regex::Regex;
// Safe pattern: no nested quantifiers, no overlapping classes
let re = Regex::new(r#"^user:[A-Za-z0-9._-]+$"#).expect("valid regex");
fn is_valid_format(s: &str) -> bool {
re.is_match(s)
}
In production, validate credentials using established libraries and avoid crafting custom regex for security-sensitive parsing. middleBrick can highlight risky regex usage in your API definitions and runtime behavior, helping you prioritize refactoring efforts. For ongoing protection, use the Pro plan to enable continuous monitoring and receive alerts if new risky patterns are detected across your API surface.
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 |