HIGH information disclosureaxum

Information Disclosure in Axum

How Information Disclosure Manifests in Axum

Information disclosure in Axum applications occurs when sensitive data is unintentionally exposed through API responses, error messages, or debug information. Unlike traditional web frameworks, Axum's async/await architecture and extractors create unique disclosure vectors that developers must guard against.

One common pattern involves improper error handling in extractors. When an extractor fails to parse a request parameter, Axum's default behavior may expose stack traces or internal implementation details:

use axum::extract::{Query, Path};
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};

async fn user_profile(Query(params): Query<HashMap<String, String>>) -> Response {
    // If params parsing fails, Axum may expose internal details
    let user_id = params.get("id").unwrap_or_else(|| "unknown");
    
    // Sensitive data exposure through debug info
    let user = find_user_by_id(user_id).await;
    if user.is_none() {
        return (StatusCode::NOT_FOUND, format!("User {} not found", user_id)).into_response();
    }
    
    // Exposing internal database IDs or implementation details
    (StatusCode::OK, user).into_response()
}

Another Axum-specific disclosure vector involves the tower::BoxError handling in middleware chains. When errors bubble up through the middleware stack without proper sanitization, they can reveal service architecture:

use tower_http::trace::TraceLayer;
use axum::routing::get;
use axum::Router;

let app = Router::new()
    .route("/api/users/:id", get(user_profile))
    .layer(
        TraceLayer::new_for_http()
            // Default trace layer may expose internal details in logs
            .on_request_fail(|error, _request| {
                // Avoid logging sensitive error details
                tracing::error!("Request failed: {}", error);
            })
    );

Extractors that wrap sensitive operations without proper error boundaries create additional disclosure risks. For example, a JSON extractor that fails on malformed input might expose schema details:

use axum::Json;
use serde::Deserialize;

#[derive(Deserialize)]
struct UserUpdate {
    email: String,
    // Sensitive field that shouldn't be exposed
    internal_notes: String,
}

async fn update_user(Json(payload): Json<UserUpdate>) -> impl IntoResponse {
    // If deserialization fails, Axum may expose schema structure
    // in error messages, revealing internal field names
    let user = update_user_in_db(payload.email, payload.internal_notes).await;
    (StatusCode::OK, user).into_response()
}

Axum-Specific Detection

Detecting information disclosure in Axum requires examining both the routing structure and the error handling patterns. The framework's modular design means vulnerabilities can hide in extractors, middleware, or even the routing configuration itself.

middleBrick's scanner specifically targets Axum's async/await patterns and extractor chains. It identifies several Axum-specific disclosure patterns:

  1. Extractor error exposure - When Query, Path, or Json extractors fail, they may expose internal validation logic or schema details
  2. Middleware error bubbling - Tower middleware errors that propagate without sanitization
  3. Debug endpoint exposure - Development-only endpoints accidentally deployed to production
  4. Configuration leakage - Server configuration details exposed through error responses

Using middleBrick to scan an Axum API endpoint:

npx middlebrick scan https://api.example.com/users/123

The scanner tests unauthenticated endpoints for information disclosure by:

  • Sending malformed requests to trigger extractor failures
  • Testing error endpoints with invalid parameters
  • Checking for debug information in 4xx/5xx responses
  • Analyzing response headers for sensitive server details

For Axum applications, middleBrick specifically examines:

// What middleBrick looks for in Axum code
- Extractors that don't handle None cases properly
- Error responses that include stack traces or internal details
- Debug features enabled in production
- Sensitive data in error messages or response bodies
- Server version headers and framework details

The scanner's LLM security checks are particularly relevant for Axum applications using AI features, as they test for system prompt leakage and prompt injection vulnerabilities that could expose sensitive configuration or training data.

Axum-Specific Remediation

Remediating information disclosure in Axum requires leveraging the framework's native error handling and response patterns. The key is implementing proper error boundaries and sanitizing all error responses before they reach clients.

Proper error handling with Axum's Result type:

use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use axum::Json;
use serde_json::json;

// Custom error type for sanitized responses
#[derive(Debug)]
enum ApiError {
    NotFound,
    ValidationError(String),
    InternalError,
}

impl IntoResponse for ApiError {
    fn into_response(self) -> Response {
        let (status, json) = match self {
            ApiError::NotFound => (
                StatusCode::NOT_FOUND,
                json!({ "error": "Resource not found" }),
            ),
            ApiError::ValidationError(msg) => (
                StatusCode::BAD_REQUEST,
                json!({ "error": msg }),
            ),
            ApiError::InternalError => (
                StatusCode::INTERNAL_SERVER_ERROR,
                json!({ "error": "Internal server error" }),
            ),
        };
        (status, Json(json)).into_response()
    }
}

async fn user_profile(
    Path(user_id): Path<String>,
) -> Result<Json<User>, ApiError> {
    let user = find_user_by_id(&user_id).await
        .ok_or(ApiError::NotFound)?;
    
    // Sanitize sensitive fields before response
    let sanitized = sanitize_user_response(&user);
    Ok(Json(sanitized))
}

Middleware for consistent error handling across all routes:

use tower_http::set_header::SetResponseHeaderLayer;
use axum::middleware::from_fn;

// Error sanitization middleware
let sanitize_middleware = from_fn(|mut req: axum::http::Request<body>, next: axum::middleware::Next<body>| async move {
    match next.run(req).await {
        Ok(response) => Ok(response),
        Err(err) => {
            // Convert internal errors to generic responses
            let sanitized = (StatusCode::INTERNAL_SERVER_ERROR, 
                Json(json!({ "error": "An unexpected error occurred" })))
                .into_response();
            Ok(sanitized)
        }
    }
});

let app = Router::new()
    .route("/api/users/:id", get(user_profile))
    .layer(sanitize_middleware);

Production-ready configuration to prevent disclosure:

use axum::http::StatusCode;
use axum::response::IntoResponse;
use tower_http::trace::DefaultMakeSpan;
use tower_http::trace::TraceLayer;

let app = Router::new()
    .route(...)
    // Disable detailed tracing in production
    .layer(TraceLayer::new_for_http()
        .make_span_with(DefaultMakeSpan::new_for_http()
            .include_headers(false)
            .include_body(false))
        .on_request_fail(|error, _req| {
            // Log minimal details
            tracing::error!("Request failed");
        }))
    // Remove server headers
    .layer(SetResponseHeaderLayer::overriding("server", ""))
    .layer(SetResponseHeaderLayer::overriding("x-powered-by", ""));

Frequently Asked Questions

How does middleBrick detect information disclosure in Axum applications?
middleBrick scans Axum APIs by sending malformed requests to trigger extractor failures, testing error endpoints with invalid parameters, and analyzing response headers and bodies for sensitive information. It specifically examines Axum's async/await patterns, extractors like Query and Json, and middleware error handling to identify disclosure vulnerabilities that could expose stack traces, internal implementation details, or sensitive data.
What makes information disclosure in Axum different from other frameworks?
Axum's async/await architecture and extractors create unique disclosure vectors. Unlike traditional frameworks, Axum's error handling through Result types and extractor failures can expose internal validation logic. The framework's modular design with tower middleware means errors can bubble up through multiple layers, potentially revealing service architecture. Axum's default debug behavior and development features also require careful configuration to prevent accidental disclosure in production.