HIGH insecure direct object referencefastapimongodb

Insecure Direct Object Reference in Fastapi with Mongodb

Insecure Direct Object Reference in Fastapi with Mongodb — how this specific combination creates or exposes the vulnerability

Insecure Direct Object Reference (BOLA/IDOR) occurs when an API exposes internal object references such as database IDs in URLs and fails to enforce that the requesting user is authorized to access the corresponding resource. Fastapi, with its dependency injection and route parameter handling, makes it straightforward to bind URL path parameters directly to database queries. When those queries use a user-supplied identifier without verifying authorization against the current subject, the endpoint becomes vulnerable.

Consider a Fastapi service that stores user data in a MongoDB collection. A route like /users/{user_id} can directly map user_id to a MongoDB _id lookup. If the handler runs db["users"].find_one({"_id": user_id}) without confirming that the authenticated subject owns or is permitted to view that document, any attacker who guesses or enumerates valid _id values can read other users’ records. This pattern is common when developers trust the client-supplied identifier and do not couple the query with the actor’s identity or tenant context.

In a typical unauthenticated or partially authenticated scenario, an attacker may not need credentials to exploit IDOR if the endpoint relies solely on object ownership checks that are incomplete. For example, an endpoint that returns user_id-scoped data might be invoked with a tampered user_id while the API still returns success because the handler never cross-checks the subject’s permissions. MiddleBrick’s BOLA/IDOR checks are designed to detect such weaknesses by correlating spec-defined parameters with runtime authorization behavior, highlighting endpoints where identifiers are used without proper constraints.

Fastapi’s OpenAPI generation can inadvertently document parameters in a way that suggests object-level access control without actually enforcing it. If the spec describes user_id as a path parameter but the implementation does not validate scope, the unauthenticated attack surface includes guessing valid identifiers. MongoDB’s use of _id values that are often sequential or UUID-based can make enumeration feasible. Thus, the combination of a flexible router, direct parameter-to-query mapping, and missing authorization logic creates a clear IDOR vector that scans like middleBrick can surface through runtime probing and spec analysis.

Mongodb-Specific Remediation in Fastapi — concrete code fixes

To mitigate IDOR when Fastapi interacts with MongoDB, couple every data access with the actor’s identity or tenant context and enforce least privilege at the query level. Avoid using raw user-supplied identifiers as the sole lookup key. Instead, bind the request subject to the query so that even a guessed identifier cannot retrieve unauthorized documents.

Below are concrete, working code examples that demonstrate secure patterns. The first shows a protected endpoint that includes the authenticated subject in the MongoDB filter. The second illustrates scoping by tenant or ownership field, which is essential in multi-tenant designs.

from fastapi import Depends, FastApi, HTTPException, status
from pymongo import MongoClient
from bson import ObjectId
import uuid

app = FastApi()
client = MongoClient("mongodb://localhost:27017")
db = client["secure_app"]
users = db["users"]

# Assume a dependency that provides the authenticated subject’s user_id
def get_current_subject() -> str:
    # In practice, this would validate tokens/sessions and return a user_id
    return "subject-uuid-here"

@app.get("/users/{user_id}")
def read_user(user_id: str, subject: str = Depends(get_current_subject)):
    # Ensure the subject is allowed to view this user document
    if not ObjectId.is_valid(user_id):
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid user ID")
    
    # Critical: include subject in query scope
    document = users.find_one({"_id": ObjectId(user_id), "owner_id": subject})
    if document is None:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Access denied")
    
    # Remove sensitive fields before returning
    document.pop("password_hash", None)
    return {"user_id": str(document["_id"]), "username": document.get("username")}

# Multi-tenant example with tenant_id field
def get_current_tenant() -> str:
    # Extract tenant from subdomain, header, or token claims
    return "tenant-uuid"

@app.get("/records/{record_id}")
def read_record(record_id: str, tenant_id: str = Depends(get_current_tenant), subject: str = Depends(get_current_subject)):
    if not ObjectId.is_valid(record_id):
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid record ID")
    
    document = db["records"].find_one({
        "_id": ObjectId(record_id),
        "tenant_id": tenant_id,
        "allowed_subjects": subject  # assuming an array field that enumerates allowed subjects
    })
    if document is None:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Record not found or insufficient permissions")
    return {"record_id": str(document["_id"]), "data": document.get("payload")}

Key remediation points: always include the subject or tenant identifier in the MongoDB filter, validate and sanitize input identifiers (e.g., check ObjectId.is_valid), and return generic error messages to avoid information leakage. Avoid exposing internal _id values directly in URLs when possible; consider mapping to opaque references if necessary. middleBrick’s scans can verify that such scoping logic exists in runtime responses and flag endpoints where identifiers are used without authorization checks.

Additionally, apply principle of least privilege to the MongoDB connection used by Fastapi. Ensure the database user has only the permissions required for the operation (e.g., find on specific collections) and avoid broad read access at the database level. Regularly rotate credentials and use network-level restrictions to reduce the impact of potential misconfigurations.

Related CWEs: bolaAuthorization

CWE IDNameSeverity
CWE-250Execution with Unnecessary Privileges HIGH
CWE-639Insecure Direct Object Reference CRITICAL
CWE-732Incorrect Permission Assignment HIGH

Frequently Asked Questions

How does middleBrick detect IDOR in Fastapi endpoints using MongoDB?
middleBrick runs unauthenticated probes that invoke endpoints with varying identifiers and checks whether data is returned without proper authorization. By correlating OpenAPI path parameters with runtime responses, it flags endpoints where object references are accepted without verifying subject ownership or tenant scope.
Can middleware or frameworks alone prevent IDOR, or do I still need to validate on each endpoint?
Frameworks can provide tools, but you must explicitly include the actor’s identity or tenant in every data access query. middleBrick highlights missing checks so you can confirm that each endpoint enforces scoping rather than relying solely on framework defaults.