HIGH regex dosactixmutual tls

Regex Dos in Actix with Mutual Tls

Regex Dos in Actix with Mutual Tls — how this specific combination creates or exposes the vulnerability

Regex Denial of Service (Regex DoS) occurs when an attacker provides input that causes a regular expression to exhibit catastrophic backtracking, consuming excessive CPU time. In Actix web applications, this risk is amplified when mutual TLS (mTLS) is used because mTLS enforces client certificate validation before the application layer sees the request. This can create a false sense of security: operators assume that because TLS authentication is strict, the endpoint is protected against malformed or malicious payloads. However, once the TLS handshake completes successfully, Actix routes process the HTTP request and any regex-based validation on headers, paths, or body parameters remains susceptible to exponential-time patterns.

Specifically, in an mTLS-enabled Actix service, the server requests and validates client certificates during the TLS handshake. After the secure channel is established, the application may still perform regex checks on untrusted inputs such as API keys, usernames, or path segments. If those regexes are not carefully constructed, an attacker can send a crafted but valid certificate-authenticated request that triggers catastrophic backtracking. Because the TLS layer already passed, logging and monitoring may mark the request as trusted, delaying detection. Moreover, if the regex is applied to a header value or JSON field that is large or repetitive, the runtime cost can spike, leading to high latency or thread exhaustion. The combination of mTLS and poorly written regex thus creates a scenario where the attack surface is not reduced as assumed, and the application remains vulnerable to resource exhaustion at the application layer despite strong transport-layer authentication.

Mutual Tls-Specific Remediation in Actix — concrete code fixes

To mitigate Regex DoS in Actix while using mutual TLS, focus on safe regex patterns and infrastructure that enforces timeouts. Avoid naive patterns that use nested quantifiers (e.g., (a+)+) on untrusted input. Prefer non-backtracking regex engines or use regex crates that implement linear-time matching for your use case. Below are concrete Actix examples that combine mTLS configuration with safe input handling.

Example 1: Actix server with mTLS and guarded regex validation

This snippet shows an Actix app that requires client certificates and validates a custom header with a safe regex. The regex avoids backtracking pitfalls by using bounded quantifiers and avoiding ambiguous alternation.

use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use actix_web::http::header::HeaderValue;
use regex::Regex;
use std::sync::Arc;

// Safe regex: uses non-overlapping patterns and bounded quantifiers
fn is_valid_api_key(value: &str) -> bool {
// Example: 8 hex characters, no nested quantifiers
let re = Regex::new(r"^[0-9a-fA-F]{8}$").unwrap();
re.is_match(value)
}

async fn index(headers: web::Headers) -> impl Responder {
match headers.get("X-API-Key") {
Some(val) => {
if let Ok(s) = val.to_str() {
if is_valid_api_key(s) {
HttpResponse::Ok().body("Valid key")
} else {
HttpResponse::BadRequest().body("Invalid key format")
}
} else {
HttpResponse::BadRequest().body("Invalid UTF-8")
}
}
None => HttpResponse::BadRequest().body("Missing header"),
}
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
// In production, paths to certificates are configured via Actix server settings
HttpServer::new(|| {
App::new()
.route("/", web::get().to(index))
})
.bind_openssl(
"0.0.0.0:8443",
{
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
let mut builder = SslAcceptor::mozilla_intermediate(openssl::ssl::SslMethod::tls()).unwrap();
builder.set_private_key_file("server.key", openssl::ssl::SslFiletype::PEM).unwrap();
builder.set_certificate_chain_file("server.crt").unwrap();
// Require client authentication
builder.set_verify(openssl::ssl::SslVerifyMode::PEER, verify_callback);
builder.build().into()
}
)
.unwrap()
.run()
.await
}

Example 2: Actix with Rustls mTLS and strict header validation

This example uses rustls for mTLS and demonstrates how to integrate certificate validation with regex checks that are safe from DoS. It emphasizes early rejection of malformed inputs to avoid unnecessary processing.

use actix_web::{dev::ServiceRequest, Error, HttpMessage};
use actix_web::http::header::HeaderValue;
use actix_web::web::Data; Data<()>;
use actix_web_httpauth::extractors::AuthenticationError;
use futures::future::{ok, Ready};
use regex::Regex;
use rustls::server::ClientCertVerified;
use rustls::server::AllowAnyAuthenticatedClient;
use std::sync::Arc;

// Safe regex for non-sensitive identifiers: no nested quantifiers
fn is_valid_identifier(s: &str) -> bool {
let re = Regex::new(r"^[a-zA-Z][a-zA-Z0-9_]{0,31}$").unwrap();
re.is_match(s)
}

fn validate_request(req: &ServiceRequest) -> Result<(), Error> {
// Example: validate a custom header after mTLS authentication
if let Some(h) = req.headers().get("X-Entity-ID") {
if let Ok(val) = h.to_str() {
if !is_valid_identifier(val) {
return Err(AuthenticationError::new("Invalid entity ID").into());
}
} else {
return Err(AuthenticationError::new("Header not UTF-8").into());
}
}
ok(req.into()).map_err(Into::into)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
// Configure rustls with client cert verification
let cert_file = "../certs/ca.crt";
let mut builder = rustls::ServerConfig::builder()
.with_safe_defaults()
.with_client_cert_verifier(Arc::new(AllowAnyAuthenticatedClient::new(vec![])));
// ... load server cert/key and client CA
let acceptor = TlsAcceptor::from(Arc::new(builder));

HttpServer::new(move || {
App::new()
.wrap_fn(|req, srv| {
validate_request(&req).map_err(|e| e.into())
.and_then(|()| srv.call(req))
})
.route("/", web::get().to(|| async { HttpResponse::Ok().body("OK") }))
})
.bind_rustls("0.0.0.0:8443", acceptor)?
.run()
.await
}

Key remediation practices include: using non-catastrophic regex patterns, validating early in the request pipeline, and combining mTLS with application-level input checks. These steps reduce the likelihood that a valid mTLS-authenticated request can trigger resource exhaustion via regex processing.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Does mutual TLS alone prevent Regex DoS attacks in Actix?
No. Mutual TLS authenticates the client at the transport layer but does not protect against application-level regex vulnerabilities. Regex DoS depends on the pattern and input; mTLS should be paired with safe regex design and input validation.
How can I test my regex patterns for catastrophic backtracking in Actix services?
Use targeted unit tests with pathological inputs (e.g., long repeated characters) and measure execution time. For production, combine safe regex patterns and consider using a regex engine or crate that guarantees linear-time matching for your patterns.