Start the app with its production configuration in CI, request the default documentation paths, and fail the build if any returns a 200 response. A ten line script catches the configuration drift that reopens Swagger UI, ReDoc or the OpenAPI JSON after a refactor.
Why a test and not a config review
Docs switches live in different places per framework: a constructor argument in FastAPI, properties in Spring, setup options in NestJS. A new profile, a copied settings file or a renamed environment variable can flip them back on. A test against the running app checks the outcome rather than the intent, which is what an outside scanner sees.
Paths to check
| Framework | Paths from the project documentation |
|---|---|
| FastAPI | /docs, /redoc, /openapi.json |
| Spring Boot with springdoc | /v3/api-docs, /v3/api-docs.yaml, /swagger-ui.html |
| NestJS with a mount path of api | /api, /api-json, /api-yaml |
If you changed paths, for example with openapi_url or jsonDocumentUrl, list your custom ones too.
A simple script
#!/usr/bin/env bash
set -u
BASE="${1:-http://localhost:8080}"
fail=0
for p in /docs /redoc /openapi.json /v3/api-docs /v3/api-docs.yaml /swagger-ui.html /api /api-json /api-yaml; do
code=$(curl -s -o /dev/null -w "%{http_code}" "$BASE$p")
if [ "$code" = "200" ]; then
echo "EXPOSED: $p returned $code"
fail=1
fi
done
exit $fail
Treat 301 and 302 with care. A redirect to a login page is fine. A redirect to the docs page is not, so follow redirects if your stack uses them and compare the final body.
Steps
- Add a CI job that builds the image or starts the app with the production profile and dummy secrets.
- Wait for the health check to pass before testing.
- Run the script against it.
- Fail the job on any exposed path and print the path.
- For intentionally public docs, replace the check with an assertion that matches your decision, for example that the docs require a login.
- Keep the list of paths in one file so a teammate adding a framework updates it in one place.
What this does not prove
It checks default and known paths only. It does not find docs mounted at an unusual path, and it says nothing about whether your routes enforce authorization. Pair it with an authenticated scan of staging and with route level tests. The per framework comparison lists the default surfaces, and what an API scanner needs before the first run covers feeding a scanner a spec when the docs are off.
OWASP recommends automated checks that continuously assess configuration effectiveness across environments, which is the same idea in small form.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how a failing check blocks a merge.
Safeguard's policies and gates can block merges on findings from your dependency scans, and a free scan is available.
Quick check
Should the test run against production?
Run it in CI against a production configured build, and optionally as a scheduled check from outside the network.
What status code should the docs paths return?
404 if the feature is off, or 401 or 403 if the docs are protected. A 200 for an anonymous request means exposure.
Sources
- FastAPI: metadata and docs URLs
- springdoc-openapi
- NestJS: OpenAPI introduction
- OWASP API8:2023 Security Misconfiguration
Last reviewed: 19 October 2026.