Fix Security Misconfiguration in Axum
Axum's minimalism is a double-edged sword. Out-of-the-box, it lacks essential security headers, resource limits, and strict CORS policies, leaving your service vulnerable to Clickjacking, XSS, and DoS. Hardening requires a proactive middleware strategy using Tower-HTTP layers to enforce a secure-by-default posture.
The Vulnerable Pattern
use ax_server::Server; use axum::{routing::get, Router}; use std::net::SocketAddr;#[tokio::main] async fn main() { // VULNERABLE: No security headers, no CORS restrictions, no timeouts, no request limits let app = Router::new().route(”/”, get(|| async { “Hello, World” }));
let addr = SocketAddr::from(([0, 0, 0, 0], 3000)); axum::Server::bind(&addr) .serve(app.into_make_service()) .await .unwrap();
}
The Secure Implementation
The secure implementation mitigates several misconfiguration vectors. First, it injects HSTS, X-Frame-Options, and CSP headers to prevent man-in-the-middle downgrades, clickjacking, and XSS. Second, it replaces the default permissive CORS (or lack thereof) with a strict origin whitelist. Third, it implements RequestBodyLimitLayer and TimeoutLayer to protect against Slowloris attacks and memory exhaustion via oversized payloads. Finally, it binds to 127.0.0.1 instead of 0.0.0.0 to prevent unintended exposure during local development.
use axum::{routing::get, Router}; use tower_http::{ cors::{Any, CorsLayer}, set_header::SetResponseHeaderLayer, limit::RequestBodyLimitLayer, timeout::TimeoutLayer, }; use http::{header, HeaderValue, Method}; use std::time::Duration;#[tokio::main] async fn main() { let secure_headers = Router::new() .route(”/”, get(|| async { “Hardened Axum Instance” })) // 1. Enforce Security Headers .layer(SetResponseHeaderLayer::overriding(header::STRICT_TRANSPORT_SECURITY, HeaderValue::from_static(“max-age=63072000; includeSubDomains; preload”))) .layer(SetResponseHeaderLayer::overriding(header::X_FRAME_OPTIONS, HeaderValue::from_static(“DENY”))) .layer(SetResponseHeaderLayer::overriding(header::X_CONTENT_TYPE_OPTIONS, HeaderValue::from_static(“nosniff”))) .layer(SetResponseHeaderLayer::overriding(header::CONTENT_SECURITY_POLICY, HeaderValue::from_static(“default-src ‘self’;”))) // 2. Strict CORS policy (Don’t use Any in production) .layer(CorsLayer::new().allow_origin(“https://trusted.com”.parse::
().unwrap()).allow_methods([Method::GET])) // 3. Prevent DoS with limits and timeouts .layer(RequestBodyLimitLayer::new(1024 * 16)) // 16KB limit .layer(TimeoutLayer::new(Duration::from_secs(10))); let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap(); axum::serve(listener, secure_headers).await.unwrap();
}
Your Axum API
might be exposed to Security Misconfiguration
74% of Axum apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.
Free Tier • No Credit Card • Instant Report
Verified by Ghost Labs Security Team
This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.