Token Leakage in Axum with Mutual Tls
Token Leakage in Axum with Mutual Tls — how this specific combination creates or exposes the vulnerability
Token leakage in an Axum service using mutual TLS (mTLS) occurs when authentication material such as client certificates or tokens intended for authorization are unintentionally exposed in logs, error messages, or application telemetry. In Axum, a Rust web framework built on Tower, requests flow through layers including headers, body parsers, and middleware. When mTLS is enforced at the transport layer (e.g., via hyper with native-tls or rustls), the server validates client certificates, but developers may still pass certificate-derived data or tokens into business logic without sanitization.
Consider a scenario where the client certificate common name (CN) or a token extracted from headers is forwarded to downstream services or written to structured logs. Axum’s extractor model (e.g., using State or custom extractors) can inadvertently propagate these values into debug output or structured event data. If logging is configured to capture headers or custom extractors include sensitive fields, tokens or certificate metadata may appear in log sinks, monitoring tools, or error traces. This exposure is especially risky when combined with insufficient log access controls or when logs are aggregated centrally without encryption at rest.
Another vector involves improper handling of authorization tokens after mTLS authentication. For example, an Axum handler might extract a bearer token from a header for scope validation but retain the token in a request extension or pass it to a background task. If the token is serialized in error responses or included in structured telemetry (e.g., OpenTelemetry spans), it can be leaked to unauthorized observers. The combination of mTLS for transport identity and token-based authorization must ensure that identity does not bleed into observable data beyond what is strictly necessary for routing or auditing.
Real-world attack patterns such as log injection or insecure error handling (related to OWASP API Security Top 10:2023 Broken Object Level Authorization and Data Exposure) amplify these risks. A misconfigured logger or an unhandled panic in Axum can serialize request extensions containing tokens, leading to exposure in stdout or log files. Similarly, certificate chains or OCSP metadata, if processed and stored without redaction, may provide attackers with insights into client identity or session context.
middleBrick’s LLM/AI Security checks and broader scan suite do not assess this specific scenario directly, but its inventory and data exposure checks can highlight related misconfigurations in API behavior and documentation. For teams using the middleBrick CLI (middlebrick scan <url>) or GitHub Action, findings may surface indirect indicators such as verbose error handling or missing input validation that correlate with token leakage risks.
Mutual Tls-Specific Remediation in Axum — concrete code fixes
Remediation focuses on ensuring tokens and certificate metadata remain confined to the authentication layer and are not propagated into logs, error responses, or downstream contexts. In Axum, configure TLS at the hyper layer and use strict extractor patterns to avoid capturing sensitive data beyond what is required.
First, enforce mTLS at the transport layer without exposing certificate fields to application logic unless necessary. Use rustls with server-side client authentication and limit the server’s trust to known CAs. Below is a minimal example of configuring TLS for an Axum service without extracting sensitive certificate fields into request extensions:
use axum::Router;
use std::net::SocketAddr;
use tower_http::trace::TraceLayer;
#[tokio::main]
async fn main() {
// Configure TLS with client authentication at the hyper/h1 layer
let tls_config = std::sync::Arc::new(
rustls::ServerConfig::builder()
.with_safe_defaults()
.with_client_auth_cert(vec![rustls::Certificate(root_cert_der().to_vec())], rustls::NoClientAuth)
.expect("valid client auth config"),
);
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let listener = tokio_rustls::TlsAcceptor::new(tls_config).unwrap().accept(std::net::TcpListener::bind(addr).unwrap());
let app = Router::new()
.route("/health", axum::routing::get(|| async { "ok" }))
.layer(TraceLayer::new_for_http());
axum::serve(listener, app.into_make_service()).await.unwrap();
}
Second, avoid including tokens or certificate-derived identifiers in logs or error payloads. Customize tracing and error handling to strip sensitive fields. For example, override TraceLayer or implement a custom layer that redacts headers such as authorization and omits request extensions that carry token metadata:
use axum::{http::HeaderName, response::IntoResponse};
use tower_http::trace::{DefaultMakeSpan, TraceLayer};
let redacted_layer = TraceLayer::new_on_http()
.make_span_with(DefaultMakeSpan::new().exclude_headers(&[HeaderName::from_static("authorization")]));
let app = Router::new()
.route("/secure", axum::routing::post(secure_handler))
.layer(redacted_layer);
async fn secure_handler(
// Use extractors that do not propagate token strings
axum::extract::Extension(state): axum::extract::Extension<AppState>,
) -> impl IntoResponse {
// Do not serialize tokens or certificate CN into responses or logs
(axum::http::StatusCode::OK, "secure endpoint")
}
Third, if token validation is required after mTLS, validate the token in memory without retaining it in structured contexts. Use short-lived tokens and avoid passing them across service boundaries in a way that could be captured by instrumentation. Ensure that any background tasks or async blocks do not capture request headers or extensions containing tokens inadvertently.
Finally, align with compliance mappings such as OWASP API Top 10 and PCI-DSS by reviewing logging configurations and ensuring that no authentication artifacts are retained beyond their intended scope. The middleBrick dashboard can help track changes over time, while the Pro plan’s continuous monitoring and GitHub Action integration can enforce thresholds to prevent regressions in security posture.