HIGH type confusionaxummutual tls

Type Confusion in Axum with Mutual Tls

Type Confusion in Axum with Mutual Tls — how this specific combination creates or exposes the vulnerability

Type confusion in an Axum service that uses mutual TLS (mTLS) arises when runtime representations of data do not match the expected types encoded in the application logic, and mTLS is used to establish client identity without correcting these mismatches. Axum is a web framework built on typed Rust handlers; when deserialization, path extraction, or header parsing produces values that are later interpreted as a different variant or structure, the mismatch can lead to unexpected behavior. Enabling mTLS adds a layer of client verification via TLS certificates, but it does not inherently validate or constrain the shape of application-level data. If the handler assumes a strongly typed structure derived from a deserialized JSON body or from path parameters, but an attacker provides values that cause the deserializer to map fields to incorrect Rust types, the runtime may treat an integer as a string, an enum as a struct, or a different variant of a tagged union as another. Because mTLS verifies the client’s certificate, the server may place additional trust in the authenticated client’s requests and process them with elevated privileges or fewer checks, inadvertently expanding the impact of the type confusion.

Consider an endpoint that expects an enum to distinguish between two resource operations, where mTLS identifies an admin client. A crafted payload that supplies a value causing the deserializer to pick the wrong enum variant can lead the server to perform an action intended for a higher-privilege context. The combination of mTLS assurance and unchecked type interpretation means the server may bypass intended authorization checks because it trusts the authenticated identity while still operating on malformed data. In OpenAPI/Swagger analysis, such issues may surface as missing constraints on numeric ranges or absent discriminators for oneOf/anyOf schemas; runtime findings can reveal that responses contain data derived from misinterpreted types. This illustrates why type-safety practices must be paired with transport-layer identity checks rather than relying on mTLS alone to enforce correct data handling.

Mutual Tls-Specific Remediation in Axum — concrete code fixes

Remediation focuses on strict validation of deserialized and extracted data, independent of mTLS client identity. Use strong Rust types, explicit discriminants, and schema validation so that type confusion cannot occur even when mTLS confirms a client’s certificate.

use axum::{
    extract::State,
    routing::post,
    Router,
};
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;
use axum::http::HeaderValue;
use axum::extract::ConnectInfo;
use axum_extra::headers::authorization::Bearer;
use axum_extra::headers::Authorization;
use axum_extra::extract::SecureHeadersLayer;
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use std::sync::Arc;
use axum::async_trait;
use axum::extract::FromRequestParts;
use axum::http::{request::Parts, StatusCode};
use axum::response::IntoResponse;

#[derive(Debug, Deserialize, Serialize)]
struct OperationRequest {
    #[serde(rename = "type")]
    operation_type: OperationType,
    #[serde(flatten)]
    details: OperationDetails,
}

#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
enum OperationType {
    Read,
    Write,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(untagged)]
enum OperationDetails {
    Read { resource_id: u64 },
    Write { resource_id: u64, payload: String },
}

async fn handle_operation(
    State(cfg): State>,
    ConnectInfo(addr): ConnectInfo,
    Authorization(token): Authorization,
    body: String,
) -> impl IntoResponse {
    // Validate mTLS-derived identity via certificate fields if needed
    let principal = cfg.validate_client(&addr);
    // Strict deserialization with serde; mismatched types will fail
    let req: OperationRequest = match serde_json::from_str(&body) {
        Ok(r) => r,
        Err(e) => return (StatusCode::BAD_REQUEST, format!("invalid payload: {e}")).into_response(),
    };
    match req.operation_type {
        OperationType::Read => {
            // handle read with explicit enum matching
            if let OperationDetails::Read { resource_id } = req.details {
                // business logic
            }
        }
        OperationType::Write => {
            if let OperationDetails::Write { resource_id, payload } = req.details {
                // business logic
            }
        }
    }
    "ok"
}

struct Config {
    ssl_acceptor: axum_server::SslAcceptorConfig,
}

impl Config {
    fn validate_client(&self, addr: &SocketAddr) -> String {
        // Placeholder for mTLS identity checks derived from certificate fields
        addr.ip().to_string()
    }
}

#[tokio::main]
async fn main() {
    let mut ssl = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
    ssl.set_private_key_file("key.pem", SslFiletype::PEM).unwrap();
    ssl.set_certificate_chain_file("cert.pem").unwrap();
    let ssl_config = axum_server::SslAcceptorConfig::new(ssl);
    let config = Arc::new(Config { ssl_acceptor: ssl_config });
    let app = Router::new()
        .route("/operation", post(handle_operation))
        .with_state(config);
    let listener = tokio::net::TcpListener::bind("0.0.0.0:8443").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

The example uses serde’s strict deserialization and explicit enum matching to avoid type confusion. Even with mTLS providing client authentication, the handler does not assume elevated trust in the payload’s structure. For additional safety, integrate schema validation libraries (such as validator or custom checks) on fields like resource_id to enforce ranges and types. In OpenAPI/Swagger, ensure the oneOf/anyOf definitions and required discriminators are present so code generation produces precise types; this aligns scan findings from middleBrick’s OpenAPI/Swagger analysis with runtime behavior.

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

Does mTLS prevent type confusion in Axum APIs?
No. Mutual TLS authenticates clients at the transport layer but does not validate application-level data shapes. Type confusion must be addressed with strict deserialization, explicit enums, and schema validation independent of mTLS.
How can middleBrick help detect type confusion in Axum APIs with mTLS?
middleBrick’s OpenAPI/Swagger analysis cross-references spec definitions with runtime findings and can highlight missing discriminators or weak constraints. Its 12 security checks run unauthenticated, so mTLS does not block scanning; you can paste the endpoint URL to receive prioritized findings and remediation guidance.