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)