The admin panel you left unlocked

Is your Swagger UI handing strangers a map of every API endpoint you have?

Swagger UI is one of the most useful things you can attach to an API. It reads your OpenAPI spec and renders an interactive page: every endpoint, every parameter, every request and response shape, with a "try it out" button. It makes your API easy to understand and easy to use.

That's the problem. It makes your API easy to understand and easy to use for everyone, including the person deciding how to attack it. A public Swagger UI is the complete, official documentation of your attack surface, written by you, kept up to date by you, and served to anyone who finds /swagger-ui/ or /v3/api-docs.

What an attacker reads off it

Normally, mapping an API is the slow part of an attack. You have to guess endpoint names, figure out which parameters each takes, work out the auth scheme, and probe for the routes nobody linked. Swagger hands all of that over in a clean, structured list.

It documents every route, including the internal and admin ones that aren't linked anywhere else: the /admin/users endpoint, the /internal/reindex job, the /debug/ helpers. It specifies each parameter and its type, so an attacker knows exactly what to send. It describes the auth scheme, so they know what they're up against. The raw /v3/api-docs JSON is the same information in machine-readable form, which means it can be fed straight into automated tooling that probes every documented endpoint without a human in the loop.

api.yoursite.com/swagger-ui/
Swagger UIvOpenAPI 3.0
GET /admin/users
POST /internal/reindex
Swagger UI OpenAPI 3.0·every route documented
Full API map, readable by anyone
The 'try it out' buttons next to admin routes are the part that turns a doc page into a console.

The "try it out" trap

Reading the map is bad enough. The interactive part can be worse. Swagger UI's "try it out" feature sends real requests to your real API from the browser. If any endpoint is missing an authorization check, which is the single most common API flaw, Swagger turns that gap into a point-and-click console for exploiting it.

An attacker doesn't even need their own tooling. They open your Swagger page, find an endpoint that should require auth but doesn't, fill in the parameters Swagger helpfully lists, and click. The fix for that underlying flaw is proper authorization on every route, and a passive external scan can't see it, because it's behind your business logic. What it can see is that you've published the menu. Whether the kitchen actually serves anyone who orders is the part a real pentest checks and a passive scan honestly can't; the published menu, though, is right there in the open.

Why it's exposed in production

Swagger gets wired into a framework during development because it's the fastest way to test your own API. Spring Boot, FastAPI, NestJS, and many others can generate it with a single dependency or annotation, and the default often exposes it at a predictable path.

Then it ships to production because nobody flipped it off. The flag that disables Swagger in prod is one line, and one line is easy to never get to. So the doc page that was meant for your dev environment ends up on api.yoursite.com, fully populated with your production routes, available to anyone who tries the standard paths. Bots try those paths automatically, because a public Swagger UI is a reliable shortcut to understanding a target.

Turn it off in production, or lock it behind auth

The clean fix is to not serve API docs publicly in production. Disable Swagger UI and the /v3/api-docs endpoint in your production profile, or put both behind authentication so only your team can reach them.

# Spring Boot: Swagger on by default at /swagger-ui/
# (no config = exposed in prod)

# FastAPI: docs at /docs and /redoc, on by default
app = FastAPI()
Disable the docs in the production profile, or gate them behind auth. One line either way.

If you have a real reason to keep the docs reachable in production, for partners or an internal team, gate them: put Swagger behind your auth layer or an authenticating proxy so a stranger gets a login, not the spec. The point is that the full map of your API shouldn't be the easiest thing on your domain to find.

Whether your Swagger UI or raw OpenAPI doc answers an anonymous request is checkable from outside by hitting the standard paths and confirming the response is the real doc, which is what SurfaceCheckr does. It probes for the Swagger and api-docs endpoints, matches the response signature so a generic page doesn't trip it, and flags an exposed one. It reads that the docs are public; it doesn't click "try it out," send requests to your endpoints, or test whether any route is missing auth, because that's active and we stay passive. The published map is the finding. Whether it should be published is a call you can make in one line of config.

Find it before someone else does.

Paste your domain. The grade and issue count are free, and you'll see in a couple of minutes exactly what's reachable from outside.