Sensitive Data Exposure

How to Fix Sensitive Data Exposure in FastAPI [March 2026] [CVE-2026-2975]

[Updated March 2026] Updated CVE-2026-2975

Overview

CVE-2026-2975 describes a vulnerability in FastApiAdmin up to version 2.2.0 involving the Custom Documentation Endpoint. The reset_api_docs function located in /backend/app/plugin/init_app.py can be manipulated to disclose information through the OpenAPI (Swagger) JSON. If an application exposes a custom docs endpoint without proper access controls, an attacker may remotely trigger the vulnerable path to leak sensitive data contained in the generated API specification, such as internal endpoints, configuration values, or tokens. This kind of information disclosure falls under CWE-200 (Information Exposure) and CWE-284 (Improper Access Control) when the documentation surface is not adequately protected. The risk is heightened in environments where documentation interfaces are publicly reachable, and an exploit has been publicly released for misuse. In real-world FastAPI deployments, this can enable attackers to map the API, discover hidden functionality, or obtain credentials embedded in configuration carried by the docs payload.

Affected Versions

FastApiAdmin <= 2.2.0

Code Fix Example

FastAPI API Security Remediation
VULNERABLE:

from fastapi import FastAPI
import os

app = FastAPI()

def reset_api_docs():
    # Vulnerable: builds OpenAPI doc and leaks sensitive data
    openapi = app.openapi()
    openapi["info"]["x_secret_token"] = os.environ.get("DOCS_TOKEN", "default_token")
    return openapi

@app.get("/docs/custom")
def custom_docs():
    return reset_api_docs()

FIXED:

from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from fastapi.openapi.utils import get_openapi

# Disable public docs by default and protect custom docs behind auth
app = FastAPI(docs_url=None, redoc_url=None)

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token")

def get_current_user(token: str = Depends(oauth2_scheme)):
    if token != "s3cr3t-token":
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token")
    return {"user": "admin"}

@app.get("/docs/custom")
def protected_docs(user: dict = Depends(get_current_user)):
    # Return a sanitized OpenAPI document without secrets
    return get_openapi(title="API", version="1.0.0", routes=app.routes)

CVE References

Choose which optional cookies to allow. You can change this any time.