HIGH bola idorfastapiapi keys

Bola Idor in Fastapi with Api Keys

Bola Idor in Fastapi with Api Keys — how this specific combination creates or exposes the vulnerability

Broken Object Level Authorization (BOLA) occurs when an API fails to enforce proper ownership or authorization checks between a subject (e.g., a user or service) and the object they are trying to access. In FastAPI applications that rely solely on API keys for authentication, BOLA vulnerabilities commonly arise because API keys typically identify the integrating client, not the specific resource owner. This leads to horizontal privilege confusion: a client with a valid key can iterate through identifiers (e.g., /users/123, /users/124) and access data belonging to other users, even though each key is associated with a distinct client.

Consider a FastAPI endpoint defined as GET /users/{user_id} that validates only the presence of an API key in a header. The key may map to a service account or a partner integration, but the endpoint does not verify that the authenticated key’s associated tenant or user matches the user_id in the path. Because the scan testing is unauthenticated, middleBrick can probe predictable numeric IDs or UUIDs with the same key and observe differing data exposure or differing response behavior, revealing BOLA. The risk is compounded when identifiers are sequential or weakly random, and when authorization logic conflates service-level access with user-level access.

Real-world attack patterns mirror findings from related CVEs in API frameworks where object-level checks are omitted or incorrectly applied. For example, an attacker could leverage a compromised API key to enumerate customer records, financial transactions, or administrative resources by iterating IDs and noting differences in status codes, response times, or data content. Even when FastAPI routes use dependency injection to retrieve a key’s metadata, failing to bind that metadata to the business object (such as tenant_id or owner_id) leaves a gap that middleBrick’s checks for BOLA/IDOR are designed to surface.

In the context of API key schemes, it is important to distinguish authentication from authorization. The key may authenticate the client, but authorization must still ensure that the authenticated client is permitted to access the specific object. Without explicit checks, FastAPI endpoints that accept user-controlled identifiers remain susceptible to horizontal BOLA. The scanner’s parallel checks for Authentication, BOLA/IDOR, and Property Authorization work together to highlight these gaps by correlating key validity with object ownership constraints.

Api Keys-Specific Remediation in Fastapi — concrete code fixes

To mitigate BOLA when using API keys in FastAPI, enforce object-level authorization that ties each key to the correct resource ownership. Below are concrete, working examples that demonstrate secure patterns.

1) Key-to-tenant binding with path parameter validation

Maintain a mapping from the API key to a tenant or user scope, and ensure every route validates that the requested resource belongs to that scope.

from fastapi import FastAPI, Depends, HTTPException, Header
from typing import Dict

app = FastAPI()

# Simulated key store: in production, use a secure lookup (e.g., database)
API_KEY_TENANT = {
    "tenant-a-key": "tenant-a",
    "tenant-b-key": "tenant-b",
}

def get_tenant_id(api_key: str = Header(...)) -> str:
    if api_key not in API_KEY_TENANT:
        raise HTTPException(status_code=401, detail="Invalid API key")
    return API_KEY_TENANT[api_key]

@app.get("/tenants/{tenant_id}/data")
def read_data(tenant_id: str, auth_tenant: str = Depends(get_tenant_id)):
    if tenant_id != auth_tenant:
        raise HTTPException(status_code=403, detail="Access to this resource denied")
    return {"tenant_id": tenant_id, "data": "secure info"}

2) Key-to-user mapping with UUID path parameters

When endpoints involve user-specific resources, resolve the key to a user identifier and compare it with the path UUID rather than trusting client-supplied IDs.

from fastapi import FastAPI, Depends, HTTPException, Header
from uuid import UUID, uuid4
from typing import Dict

app = FastAPI()

# Example mapping: key -> owning user_id (as string)
API_KEY_USER: Dict[str, str] = {
    "user-key-xyz": str(uuid4()),  # in practice, store persistently
}

def get_user_id_from_key(api_key: str = Header(...)) -> str:
    if api_key not in API_KEY_USER:
        raise HTTPException(status_code=401, detail="Invalid API key")
    return API_KEY_USER[api_key]

@app.get("/users/{user_id}/profile")
def get_profile(user_id: UUID, actor_id: str = Depends(get_user_id_from_key)):
    if str(user_id) != actor_id:
        raise HTTPException(status_code=403, detail="Forbidden: cannot access other user profiles")
    return {"user_id": user_id, "profile": "safe data"}

3) Centralized authorization dependency

Encapsulate checks in a reusable dependency to keep route logic clean and ensure consistent enforcement across endpoints.

from fastapi import Depends
from typing import Callable

def authorize_object_owner(
    object_id: str,
    get_actor_id: Callable[[], str] = Depends(get_user_id_from_key)
) -> None:
    if object_id != get_actor_id():
        raise HTTPException(status_code=403, detail="Object-level authorization failed")

@app.get("/records/{record_id}")
def read_record(record_id: str, _: None = Depends(authorize_object_owner)):
    return {"record_id": record_id, "content": "authorized data"}

These patterns emphasize that API keys should map to a principal with defined scopes, and that every route accepting an object identifier must validate that principal against the identifier. Avoid using path parameters alone to infer permissions, and do not rely on obscurity or non-sequential identifiers as a substitute for proper checks. middleBrick’s checks for BOLA/IDOR and Property Authorization can validate that such controls are present and effective.

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

Why does using API keys alone not prevent BOLA in FastAPI endpoints?
API keys typically authenticate the client or integration, but they do not encode ownership of specific objects. Without explicit checks that bind the key to the requested resource (e.g., tenant_id or user_id), a client can iterate over object identifiers and access data belonging to other subjects, resulting in horizontal BOLA.
Can middleware or route-level dependencies fully protect against BOLA in FastAPI with API keys?
Middleware can help with global checks, but BOLA prevention requires per-route or per-resource authorization that compares the key’s associated subject (tenant or user) to the object identifier in the request path. Centralized dependencies that enforce this comparison consistently across endpoints reduce risk.