HIGH type confusionaxumapi keys

Type Confusion in Axum with Api Keys

Type Confusion in Axum with Api Keys — how this specific combination creates or exposes the vulnerability

Type confusion in an Axum API that uses API keys typically occurs when header or query parameters intended to carry a string key are deserialized into a mismatched type, such as an integer or a complex struct, bypassing expected validation. This mismatch can allow an attacker to supply a numeric or structured value where a string key is expected, potentially causing the application to treat the key as a different object or skip authorization checks entirely.

In Axum, API keys are often extracted from request headers using extractors such as Extension, custom guards, or dedicated key extraction logic. When the extractor does not enforce strict string typing or when the key is parsed into a broader type (e.g., deserializing into a numeric ID or a generic JSON value), a type confusion arises. For example, if an API key is passed as a header and bound to a route parameter expecting a different type, Axum’s router may coerce the value, leading to incorrect authorization decisions.

Consider an endpoint that retrieves a user profile and relies on an API key for access control. If the key is deserialized into a numeric type instead of a string, an attacker might supply an integer that maps to another valid user’s key, enabling BOLA/IDOR through type confusion rather than direct guessing. The scanner’s checks around Authentication and BOLA/IDOR would flag this when an unauthenticated request with a manipulated key yields data belonging to another user.

OpenAPI/Swagger specifications can inadvertently contribute to type confusion if the schema for the header or query parameter is defined as type: integer or uses oneOf with loosely typed references. During runtime, Axum may bind the incoming value to the declared type, and if the spec does not strictly enforce string format, the deserialized key may not match the application’s expected structure. This discrepancy is identified in the scan’s Authentication and Property Authorization checks, which correlate spec definitions with runtime behavior to detect mismatches.

The LLM/AI Security checks further highlight risks when API keys are exposed through model interactions, such as system prompt leakage or unsafe consumption patterns. If an API key is passed through unchecked inputs and reflected in error messages or logs, it may be exfiltrated via prompt injection techniques. The scanner’s active probing and output analysis help identify whether key handling logic is vulnerable to disclosure or misuse in AI-assisted contexts.

Api Keys-Specific Remediation in Axum — concrete code fixes

To remediate type confusion when using API keys in Axum, enforce strict string typing for keys at the extractor level and validate format before use. Avoid binding keys to numeric or loosely typed parameters, and ensure the deserialization path rejects malformed or mismatched types.

Below are concrete, working examples of API key handling in Axum that prevent type confusion.

use axum::{
    extract::Extension,
    routing::get,
    Router,
};
use std::net::SocketAddr;
use serde::{Deserialize, Serialize};

// Define a strongly typed wrapper for the API key
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
struct ApiKey(String);

// Custom extractor that ensures the header is a valid string key
impl axum::extract::FromRequest<S> for ApiKey
where
    S: axum::extract::SyncExtensionSource,
{
    type Rejection = axum::http::StatusCode;

    fn from_request(req: axum::http::Request<S::Body>) -> Result<Self, Self::Rejection> {
        let header_value = req.headers()
            .get("X-API-Key")
            .and_then(|v| v.to_str().ok())
            .ok_or(axum::http::StatusCode::UNAUTHORIZED)?;

        // Reject non-string or empty values at extraction time
        if header_value.is_empty() {
            return Err(axum::http::StatusCode::UNAUTHORIZED);
        }

        // Ensure the key conforms to expected format (e.g., alphanumeric)
        if !header_value.chars().all(|c| c.is_ascii_alphanumeric()) {
            return Err(axum::http::StatusCode::UNAUTHORIZED);
        }

        Ok(ApiKey(header_value.to_string()))
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct UserProfile {
    id: u64,
    name: String,
}

async fn get_profile(Extension(key): Extension<ApiKey>) -> String {
    // Key is guaranteed to be a valid string at this point
    format!("Profile for key: {}", key.0)
}

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/profile", get(get_profile))
        .layer(Extension(ApiKey("secret123".to_string())));

    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}

In this example, the ApiKey extractor enforces string-only input and rejects malformed or non-conforming values, preventing type confusion. The use of a dedicated struct ensures that the key is treated consistently across the application, and the validation logic blocks numeric or structured values that could lead to privilege escalation or BOLA.

Additionally, align your OpenAPI spec to explicitly define the API key header as type: string with a format such as password or a custom pattern. This consistency between spec and runtime further reduces the risk of type confusion and supports accurate scanning by middleBrick’s Authentication and Property Authorization checks.

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

Why does specifying the API key header as an integer in the OpenAPI schema increase risk?
Defining the key as an integer or numeric type allows Axum to coerce incoming values into that type, which can cause type confusion. An attacker may supply a crafted integer that maps to another valid key or bypass checks, leading to unauthorized access or BOLA/IDOR.
How does middleBrick detect type confusion risks related to API keys in Axum?
middleBrick cross-references the OpenAPI schema definitions with runtime behavior, checking for type mismatches in Authentication and Property Authorization checks. It also examines whether keys are handled through strict string extractors and validates that rejection logic is in place for malformed inputs.