Exposed API docs: stop publishing the map of every endpoint
Gating Swagger/OpenAPI behind auth (or turning it off in production) removes a complete map of your API.
The threat
The scanner requested a docs path (a Swagger UI page or an OpenAPI schema like /openapi.json or /v3/api-docs) and got the document back. Interactive API docs are wonderful in development and normal to leave on by a framework default, which is exactly why they so often ship to production by accident.
Public, that schema is a complete, annotated map of your API: every endpoint, every HTTP method, every parameter and its type, request and response shapes, and the auth scheme each route expects. It is the reconnaissance an attacker would otherwise have to assemble by hand, handed over in one file, pointing straight at the endpoints worth probing.
The exact fix
Turn the docs off in production, or put them behind authentication. Turning them off is the common choice.
Disable in production (pick your framework):
# Spring Boot (springdoc)
springdoc.api-docs.enabled=false
springdoc.swagger-ui.enabled=false
// ASP.NET (Swashbuckle): only in development
if (app.Environment.IsDevelopment()) {
app.UseSwagger();
app.UseSwaggerUI();
}
// Express (swagger-ui-express): skip in production
if (process.env.NODE_ENV !== 'production') {
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(spec));
}
# FastAPI: no docs endpoints in production
app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)
If you need docs in production, require auth. Put them behind basic auth at the gateway, SSO, or an internal-only route, and block the public schema paths (/swagger*, /openapi.json, /v3/api-docs) at your reverse proxy.
Hiding the map does not lock the doors. Every endpoint the docs revealed is still live. Use this as the prompt to confirm each one actually enforces authorization, because an attacker can hit those routes whether or not the docs are visible.
Verify it
curl -s -o /dev/null -w '%{http_code}\n' https://yourdomain.com/openapi.json
You want 404 (off) or 401/403 (gated). Check /swagger-ui.html and /v3/api-docs too; none should return a 200 with a body containing "openapi": or "swagger":.
Proof
The ApeCyber scanner catches an open schema with a single GET from the outside, touching nothing, on every scan. A production API should answer that request with a 404 or an auth challenge, never a full endpoint map, and closing this recovers a clean โ10 on the posture score.