Header Injection in Axum with Jwt Tokens
Header Injection in Axum with Jwt Tokens — how this specific combination creates or exposes the vulnerability
Header Injection in Axum when using JWT tokens typically arises when application code directly forwards untrusted HTTP headers into JWT processing logic, such as header-based token extraction or custom authorization schemes. Axum is a Rust web framework that does not perform automatic header validation beyond what you implement; therefore, passing user-supplied headers into token parsing or middleware without strict validation can lead to injection-style issues, including token manipulation or bypass attempts.
For example, if an API extracts a JWT from a custom header like x-access-token or authorization and does not enforce a strict allowlist of permitted header names, an attacker may inject additional headers or duplicate headers to alter behavior. Certain Axum middleware combinations or custom extractors might concatenate or select headers in a way that makes the application accept a modified token or fall back to an insecure parsing path. While this is not a classic HTTP header injection in the sense of smuggling requests through a proxy, it can lead to JWT confusion attacks, where an attacker-supplied header causes the server to validate an unintended token or skip validation entirely.
Another scenario involves forwarding headers to downstream services or logging mechanisms without sanitization. If Axum applications log raw headers that include JWTs and those logs are later used to reconstruct requests, injected newline characters in header values could split log entries and obscure the source of a forged token. The OWASP API Top 10 category '2023:5 — Security Misconfiguration' and related implementation patterns highlight the risks of overly permissive header handling in API frameworks.
In Axum, because OpenAPI/Swagger spec analysis (2.0, 3.0, 3.1) with full $ref resolution cross-references spec definitions with runtime findings, scans can flag inconsistencies between declared authentication requirements and actual header usage. This helps identify places where JWT handling may be inadvertently exposed to header-level manipulation, even when the framework itself does not introduce the flaw.
Jwt Tokens-Specific Remediation in Axum — concrete code fixes
Remediation focuses on strict header source validation, canonical token extraction, and avoiding any dynamic header-based routing of JWTs. Use Axum’s extractor patterns to enforce a single, predictable source for JWTs, such as the authorization header with the Bearer scheme, and reject requests that do not conform.
Example of secure JWT extraction in Axum using the jsonwebtoken crate and tower-http middleware:
use axum::{
async_trait,
extract::{self, FromRequest},
http::{self, request::Parts, HeaderValue},
};
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
use std::convert::Infallable;
const EXPECTED_HEADER: &str = "authorization";
const BEARER_PREFIX: &str = "Bearer ";
struct JwtToken(String);
#[async_trait]
impl FromRequest<S> for JwtToken {
type Rejection = (http::StatusCode, String);
async fn from_request(req: extract::Request) -> Result<Self, Self::Rejection> {
let parts = req.into_parts();
// 1) Ensure exactly one 'authorization' header exists
let headers = &parts.headers;
let auth_values: Vec<&HeaderValue> = headers.get_all(EXPECTED_HEADER).iter().collect();
if auth_values.len() != 1 {
return Err((http::StatusCode::UNAUTHORIZED, "Missing or duplicate authorization header".into()));
}
let value = auth_values[0].to_str().map_err(|_| (http::StatusCode::UNAUTHORIZED, "Invalid header encoding"))?;
// 2) Reject malformed values and enforce Bearer prefix
if !value.starts_with(BEARER_PREFIX) {
return Err((http::StatusCode::UNAUTHORIZED, "Invalid authorization scheme"));
}
let token = value[BEARER_PREFIX.len()..].trim();
if token.is_empty() {
return Err((http::StatusCode::UNAUTHORIZED, "Empty token"));
}
// 3) Validate token structure and signature using a known decoding key
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = true;
let _claims = decode::(
token,
&DecodingKey::from_secret(&b"your-secret"[..]),
&validation,
)
.map_err(|_| (http::StatusCode::UNAUTHORIZED, "Invalid token"))?;
Ok(JwtToken(token.to_string()))
}
}
// Usage in a route:
// async fn protected_route(token: JwtToken) -> String { "ok" }
Key practices:
- Do not concatenate or merge multiple headers to form a token; use a single, designated header.
- Enforce a strict allowlist of permitted header names at the middleware or extractor level.
- Normalize header names to lowercase before comparison to avoid case-sensitive bypass attempts.
- Reject requests with malformed or missing schemes, and ensure token strings are trimmed to avoid whitespace-based confusion.
- Combine this approach with Axum’s middleware for rate limiting and logging sanitization to prevent log injection via newline characters in header values.
For teams using the middleBrick ecosystem, the CLI tool (middlebrick scan <url>) can detect inconsistencies between declared authentication in OpenAPI specs and actual runtime header usage, while the Web Dashboard tracks these findings over time. The Pro plan’s continuous monitoring can schedule scans to catch regressions in header handling as APIs evolve.