HIGH excessive data exposureaxummongodb

Excessive Data Exposure in Axum with Mongodb

Excessive Data Exposure in Axum with Mongodb — how this specific combination creates or exposes the vulnerability

Excessive Data Exposure occurs when an API returns more data than necessary for a given operation, often including sensitive fields such as passwords, internal identifiers, or PII. In an Axum application using MongoDB as the backend, this commonly arises from mapping entire database documents directly into API responses without explicit field selection. Because Axum handlers often serialize structs derived from MongoDB query results, developers may inadvertently expose fields like password_hash, email, or internal metadata if the response DTO mirrors the MongoDB document shape.

For example, a GET user endpoint might query a MongoDB collection and return the full document to the client. If the document contains fields that should be restricted based on context (e.g., admin vs. regular user), the API performs no runtime filtering. This becomes a risk when responses include sensitive data that is not required for the client, increasing the impact of data leaks through logs, browser history, or network inspection. The issue is compounded when APIs rely on unauthenticated or weakly authenticated endpoints, as excessive data exposure can reveal information useful for further attacks such as BOLA or IDOR.

middleBrick scans identify this category by comparing the OpenAPI schema with runtime responses and flagging fields that are not documented or are unexpectedly present. This is especially relevant for Axum + MongoDB stacks where projection or explicit DTOs are not consistently applied. Without explicit control over which fields are returned, applications may violate the principle of least privilege in data exposure.

Mongodb-Specific Remediation in Axum — concrete code fixes

To prevent Excessive Data Exposure in Axum with MongoDB, use explicit projection and dedicated response structs rather than returning raw MongoDB documents. This ensures only intended fields are serialized and sent to the client. Below are concrete, working examples using the official MongoDB Rust driver with Axum.

1. Define a restricted response DTO

Create a struct that includes only the fields safe for public consumption. Avoid reusing database models directly in API responses.

#[derive(serde::Serialize)]
struct UserPublicResponse {
    id: String,
    username: String,
    email: String,
    created_at: chrono::DateTime<chrono::Utc>,
}

#[derive(serde::Serialize)]
struct UserAdminResponse {
    id: String,
    username: String,
    email: String,
    role: String,
    created_at: chrono::DateTime<chrono::Utc>,
    last_login: Option<chrono::DateTime<chrono::Utc>>,
}

2. Use projection when querying MongoDB

Apply projection to retrieve only necessary fields from MongoDB. This reduces network traffic, storage use, and accidental exposure of sensitive fields.

use mongodb::{bson::{doc, Document}};

async fn get_user_projected(
    collection: &mongodb::Collection<Document>,
    user_id: &str,
) -> Result<Option<Document>, mongodb::error::Error> {
    let filter = doc! { "_id": user_id };
    let projection = doc! {
        "username": 1,
        "email": 1,
        "created_at": 1,
        "_id": 0, // exclude _id if you map to a custom id field
    };
    let opt_user = collection
        .find_one(filter, Some(projection))
        .await?;
    Ok(opt_user)
}

3. Map to DTOs and integrate with Axum handlers

Convert the projected document into a safe response struct before returning it from an Axum handler. This keeps your routes clean and enforces the data contract.

use axum::Json;
use serde::Serialize;

async fn get_user_handler(
    State(db): State<Arc<MongoDbState>>,
    Path(user_id): Path<String>,
) -> Result<Json<UserPublicResponse>, (StatusCode, String)> {
    let doc = get_user_projected(&db.users, &user_id)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?
        .ok_or_else(|| (StatusCode::NOT_FOUND, "User not found".to_string()))?;

    let user = UserPublicResponse {
        id: doc.get_str("_id").unwrap_or("").to_string(),
        username: doc.get_str("username").unwrap_or("").to_string(),
        email: doc.get_str("email").unwrap_or("").to_string(),
        created_at: doc.get_datetime("created_at").unwrap_or_default(),
    };
    Ok(Json(user))
}

4. Use aggregation for conditional exposure (admin only fields)

For endpoints that serve multiple roles, use MongoDB aggregation to conditionally include or exclude fields based on the requester’s role. This example assumes the role is resolved before the aggregation.

async fn get_user_adaptive(
    collection: &mongodb::Collection<Document>,
    user_id: &str,
    requester_role: &str,
) -> Result<Option<Document>, mongodb::error::Error> {
    let match_stage = doc! {
        "$match": doc! { "_id": user_id }
    };
    let project_public = doc! {
        "$project": doc! {
            "username": 1,
            "email": 1,
            "created_at": 1,
            "_id": 0,
        }
    };
    let project_admin = doc! {
        "$project": doc! {
            "username": 1,
            "email": 1,
            "role": 1,
            "last_login": 1,
            "created_at": 1,
            "_id": 0,
        }
    };
    let project_stage = if requester_role == "admin" {
        project_admin
    } else {
        project_public
    };

    let cursor = collection
        .aggregate(vec![match_stage, project_stage], None)
        .await?;
    let mut cursor = cursor.collect::<Document>();
    if cursor.is_empty() {
        Ok(None)
    } else {
        Ok(cursor.remove(0))
    }
}

By combining projection, DTOs, and aggregation, you ensure that Axum endpoints backed by MongoDB adhere to the principle of least privilege and avoid Excessive Data Exposure.

Related CWEs: propertyAuthorization

CWE IDNameSeverity
CWE-915Mass Assignment HIGH

Frequently Asked Questions

Does using MongoDB projection fully prevent Excessive Data Exposure in Axum APIs?
Projection reduces exposure at the database layer, but you must also enforce field selection in your Axum response DTOs. Never rely solely on projection; always serialize through explicit structs for API responses.
Can middleBrick detect Excessive Data Exposure in Axum + MongoDB setups?
Yes. middleBrick compares your OpenAPI schema with runtime responses and flags fields present in responses but not documented or unexpected for the given endpoint. This helps identify excessive exposure even when using MongoDB.