HIGH type confusionaxum

Type Confusion in Axum

How Type Confusion Manifests in Axum

Type confusion occurs when an application mistakenly treats data of one type as another, leading to unexpected behavior. In axum, this often appears when request data is parsed into a struct without proper validation, and then used in contexts where a different type is expected. For example, a route may expect a String identifier but receives a JSON object that is unknowingly coerced into a numeric type due to improper deserialization. This can lead to IDOR (Insecure Direct Object Reference) vulnerabilities if the system assumes a numeric ID but an attacker supplies a string path parameter that bypasses authorization checks.

Common patterns include:

  • Using req.json().await to deserialize into a struct that does not enforce type boundaries, allowing non-string values to pass through undetected.
  • Relying on PathParam::parse::() without validating that the path segment contains only digits, which can be exploited if the underlying handler later treats the value as a string.
  • Allowing user-controlled input to be used directly in database queries without type-aware sanitization, enabling injection via type juggling.

Specific attack vectors in axum involve the interaction between extractors and typed handlers. When an extractor such as Path or Query is combined with a custom type that implements FromStr or Deserialize, the framework may silently coerce malformed input. For instance, a route defined as /api/users/:id with a handler expecting Path will reject non-numeric segments, but if the handler instead accepts Path and later attempts to parse the value as an integer, an attacker can supply a string that contains non-numeric characters followed by a numeric suffix, causing the application to treat part of the input as valid while the remainder is ignored, potentially leading to data leakage or privilege escalation.

Another manifestation is in the handling of JSON bodies where the server expects an object with a specific field type but receives a different structure. If the server uses Json extractor and the target type T has a field annotated with Option<String> but the incoming JSON provides a numeric value for that field, the deserializer may convert the number to a string implicitly, causing downstream logic that expects a string to behave differently. This can bypass checks that rely on type equality, opening pathways for BOLA (Broken Object-Level Authorization) attacks where an attacker manipulates field types to access resources they should not.

These scenarios illustrate how type confusion can arise not from explicit casting but from the implicit trust placed in extractors and the lack of rigorous type enforcement at the boundary of request handling. The consequence is often a security flaw that manifests as unauthorized data access, privilege escalation, or injection, all rooted in the mismatch between the expected and actual data types.

Axum-Specific Detection

Detecting type confusion in an axum application requires both runtime testing and static analysis of request handling logic. middleBrick provides a black-box scan that evaluates the unauthenticated attack surface by submitting crafted URLs and analyzing the responses for anomalies indicative of type confusion. When middleBrick scans an endpoint, it looks for patterns such as unexpected HTTP status codes, error messages that reveal internal type handling, or responses that contain mixed-type data structures where a string was expected.

For instance, consider an endpoint /api/items/:id that uses Path<u64> to extract the identifier. middleBrick can submit a request with a non-numeric path segment like /api/items/abc123. If the application treats this as a valid identifier and proceeds to query the database, middleBrick will flag the deviation from strict numeric validation as a potential type confusion issue. The scanner also checks whether the response includes detailed error messages that expose internal type conversion logic, which can aid an attacker in crafting further payloads.

Additionally, middleBrick examines JSON body endpoints where the server expects a specific schema. By sending a payload where a field designated as a string contains a numeric value, the scanner can determine if the application silently coerces the value and proceeds without raising validation errors. This is particularly relevant for routes that use Json<MyStruct> extractors with fields defined as String but are later compared against numeric thresholds without explicit casting. The scanner reports such findings under the Input Validation category, providing a severity rating and a description of the potential impact.

To aid developers, middleBrick includes a CLI tool that can be run locally to test specific routes. Using the command middlebrick scan /api/items/:id, the tool sends a series of test inputs and captures the responses, allowing developers to observe how type handling behaves under different inputs. This hands-on approach complements the cloud-based dashboard, where users can track detection history and receive alerts when new type confusion patterns are identified across their API surface.

Axum-Specific Remediation

Remediation of type confusion vulnerabilities in axum centers on enforcing strict type boundaries at the point of request parsing. The recommended approach is to validate input explicitly before it enters downstream logic, rather than relying on implicit conversions performed by extractors or downstream libraries.

One effective pattern is to use custom extractors that enforce the expected type. For example, instead of directly extracting a path parameter as a string and later parsing it, define a dedicated extractor that only accepts numeric values:

use axum::extract::FromRequestExt; use axum::http::StatusCode; use axum::response::IntoResponse; use axum::Json; use serde::Deserialize; use thiserror::Error; use std::convert::Infallible; use validator::{Validate, ValidationError>; use axum::extract::Path; use axum::http::Request; use axum::middleware::Next; use axum::response::Response; use std::future::Ready; use std::pin::Pin; use std::task::{Context, Poll}; use std::marker::PhantomPinned>; #[derive(Validate)] struct NumericId(u64); impl FromRequestExt for NumericId { type Rejection = (StatusCode, Json<String>); async fn from_request(req: Request, _: &mut ext::Extensions) -> Result { let param = req.extensions().get::().map_err(|_| (StatusCode::BAD_REQUEST, Json::from("ID must be numeric")))?; Ok(NumericId(id)) } }

By encapsulating the parsing logic within a custom extractor, the application ensures that only properly typed values reach the handler, eliminating the risk of silent coercion.

Another remediation strategy involves using schema validation libraries such as validator to check the structure and type of JSON payloads before they are deserialized into application structs. For instance, when an endpoint expects a field named age to be a numeric string, the validation rule can be defined as:

#[derive(Validate)] struct UserInput { #[validate(range(min = 0, max = 150))] age: String, } impl UserInput { fn validate_age(&self) -> Result<(), ValidationError> { let age_str = &self.age; if age_str.parse::().is_err() { return Err(ValidationError::new("Age must be a valid integer")); } Ok(()) } }

By explicitly validating that the string can be parsed into an integer, the application prevents type confusion that could arise from unexpected numeric inputs.

For route handlers that perform database queries based on user-provided identifiers, it is advisable to separate the identifier extraction from its usage. First, extract the identifier as a string, validate it against a whitelist of allowed patterns, and then convert it to the appropriate type only after validation. This two-step process ensures that any deviation from the expected format is caught early, reducing the attack surface for injection or privilege escalation attacks.

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