HIGH header injectionaxumapi keys

Header Injection in Axum with Api Keys

Header Injection in Axum with Api Keys — how this specific combination creates or exposes the vulnerability

Header Injection occurs when user-controlled data is placed directly into HTTP headers without validation or sanitization. In Axum, this often arises when API keys or other header-derived values are forwarded to downstream services or reflected into responses. Because HTTP headers can carry multiple values and are parsed differently than path or query parameters, unsanitized header content can enable request smuggling, header splitting, or injection of additional headers (e.g., x-forwarded-for, x-api-key, authorization).

When API keys are handled via headers (commonly x-api-key), Axum extracts the value and may pass it to authorization logic or logging. If the application reflects header values in error messages, response headers, or logs without strict allowlisting, an attacker can inject newline sequences (e.g., %0D%0A or \r\n) to create illicit headers. For example, a key like abc\r\nX-Admin: true could cause the server to interpret an extra header if the value is concatenated into another header downstream.

Axum does not automatically sanitize headers; responsibility falls to the developer. Consider a route that forwards the API key to an upstream service via a header:

let api_key = request.headers().get("x-api-key").and_then(|v| v.to_str().ok());
// Risky: direct forwarding without validation
if let Some(key) = api_key {
    let _ = forwarded_request.headers_mut().insert("x-api-key", key.parse().unwrap());
}

If key contains newline characters, insert may produce malformed headers depending on the underlying HTTP implementation, enabling Header Injection. Similarly, logging the raw header value can lead to log injection, where injected newlines alter log structure and potentially facilitate log forging or injection attacks.

Combinations of Axum middleware (e.g., tower-http for authentication) and custom header handling increase risk if validation is inconsistent. The API key header may be trusted implicitly, but an attacker who can influence it (via client-side code, subdomain compromise, or a proxy) can exploit injection to escalate privileges, bypass rate limiting, or poison caches.

In the context of an unauthenticated scan, middleBrick checks whether header values are reflected or forwarded without canonicalization. It does not assume the presence of a vulnerability but highlights where header injection could occur based on reflected inputs and missing allowlists.

Api Keys-Specific Remediation in Axum — concrete code fixes

Remediation focuses on strict validation, avoiding header reflection, and safe propagation. Prefer extracting API keys from a dedicated, non-reflected source (e.g., a secure vault or environment variable) rather than trusting incoming headers for authorization.

1. Validate and sanitize header values

Never forward or reflect raw header values. Use a strict allowlist of characters for API keys and reject any input containing control characters or whitespace.

use axum::http::HeaderValue;

fn is_valid_api_key(s: &str) -> bool {
    // Allow only alphanumeric, hyphen, underscore, and base64-like chars
    s.chars().all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '.' || c == '~')
}

async fn handler(
    request: Request<Body>,
) -> Result<Response<Body>, (StatusCode, String)> {
    let opt = request.headers().get("x-api-key")
        .and_then(|v| v.to_str().ok())
        .filter(|&key| is_valid_api_key(key));

    match opt {
        Some(key) => {
            // Safe: key is validated, no injection possible
            let mut forwarded = Request::new(Body::empty());
            *forwarded.headers_mut() = request.headers().clone();
            // Replace with a sanitized value if needed
            forwarded.headers_mut().insert("x-api-key", HeaderValue::from_str(key).unwrap());
            // Continue processing
            Ok(Response::new(Body::from("ok")))
        }
        None => Err((StatusCode::UNAUTHORIZED, "Invalid API key".into())),
    }
}

2. Avoid reflecting API keys in responses or logs

Do not include raw API key values in response headers, bodies, or logs. If logging is necessary, hash or truncate and avoid newlines.

async fn handler(
    request: Request<Body>,
    State(config): State<Arc<Config>>
) -> impl IntoResponse {
    if let Some(raw) = request.headers().get("x-api-key") {
        if let Ok(s) = raw.to_str() {
            if is_valid_api_key(s) {
                config.logger.log(&format!("key_id={}", hash_key(s))); // safe log
            }
        }
    }
    // Respond without echoing the key
    (StatusCode::OK, "Request accepted")
}

3. Use middleware for centralized validation

Implement a tower layer that validates API keys and rejects malformed headers before they reach your routes.

use tower::Layer;
use tower_http::ServiceExt;

struct ApiKeyLayer;

tower::layer::util::make_service_fn(|_conn: &http::server::conn::AddrStream| {
    async { Ok::<_, tower_http::service::ServeDir>(ApiKeyLayer) }
});

// In practice, combine axum extractors with a validation layer that ensures
// headers are clean before routing.
async fn validate_key_layer(mut req: Request<B>) -> Result<Request<B>, (StatusCode, String)> {
    if let Some(h) = req.headers().get("x-api-key") {
        if let Ok(val) = h.to_str() {
            if is_valid_api_key(val) {
                return Ok(req);
            }
        }
    }
    Err((StatusCode::UNAUTHORIZED, "Invalid key".into()))
}

By combining strict validation, avoiding reflection, and centralizing checks, you mitigate Header Injection risks specific to API key handling in Axum.

Frequently Asked Questions

Can Header Injection in Axum with API keys affect authentication flows?
Yes. If an API key header is reflected or forwarded unsanitized, an attacker can inject newline characters to create additional headers such as Authorization or manipulate downstream routing, potentially bypassing intended authentication.
Does middleBrick test for Header Injection in Axum API key handling?
middleBrick runs checks for input validation and header reflection. In an unauthenticated scan, it flags where user-controlled header values are used without canonicalization, helping you identify risky patterns in Axum API key handling.