Publishing Your Complete API Surface by Accident
The best reconnaissance does not require probing. It requires reading.
During an external assessment against a global infrastructure provider, a request to a path that most organizations never think to check returned a response that made the next several hours significantly more productive — not because it revealed a direct exploit, but because it described exactly where to look for one.
GET /api/v2/openapi.json HTTP/1.1
Host: api.example-infra.com
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 847293
A 847-kilobyte JSON file. An OpenAPI specification for the entire v2 API. No authentication required.
Finding the Files
Subdomain enumeration during the initial reconnaissance phase returned a list of hostnames that followed naming conventions consistent with API infrastructure. The company operated a large platform: compute, storage, networking, and a set of managed services that customers configured through a web interface and, for more complex workflows, directly through API calls.
API hosts in large deployments tend to document themselves. Developers build APIs against specification files, frameworks generate documentation endpoints automatically, and the documentation is useful enough during development that it rarely gets explicitly disabled when the code reaches production.
The paths I check vary by framework. Most specification files live at predictable locations:
/openapi.jsonand/openapi.yaml/swagger.jsonand/swagger.yaml/api-docsand/api-docs.json/v1/openapi.json,/v2/openapi.json(versioned paths)/api/swaggerand/api/swagger-ui- Framework-specific paths:
/q/openapifor one common Java framework,/api/schema/for certain Python frameworks
I checked each discovered API host against this list. Three of them responded. Each returned a different specification — different service, different scope, different information — but all three were accessible without any authentication.
What the First Spec Contained
The largest of the three files described the primary customer-facing API. Across 847 kilobytes of JSON, it enumerated every endpoint in the v2 API surface.
Reading an OpenAPI spec is different from reading API documentation written for external developers. The spec is generated directly from the codebase annotations. It includes everything the developer annotated, without editorial filtering.
The endpoint inventory was comprehensive. Grouped by tag, the spec documented:
Account management operations. Endpoints for creating, reading, updating, and deleting customer accounts. Several of these were marked in the spec's description fields with notes that were clearly written for internal developers: one endpoint description read "admin-only, validates against internal allowlist before processing" — helpful guidance for developers, also helpful for understanding which endpoints were supposed to be access-controlled.
Billing and subscription operations. Endpoints for retrieving invoice data, modifying subscription tiers, and applying promotional credits. The spec documented parameter names and data types in detail, including an override_billing_cycle parameter on a subscription modification endpoint that was annotated: "internal use only, bypasses proration calculations."
Infrastructure provisioning endpoints. Endpoints for managing compute instances, storage volumes, and network configurations. These included administrative operations — bulk provisioning, resource reallocation, forced termination — that were separately grouped but visible in the same spec.
Internal service communication endpoints. A set of endpoints prefixed /internal/ that the spec described as used by other platform services for inter-service coordination. These included callback endpoints, event notification receivers, and status synchronization operations. Their presence in the externally-accessible spec was clearly unintentional — the descriptions referenced internal service names and assumed an internal caller.
The spec also documented the authentication requirements for each endpoint. Most required a standard Bearer token. Several of the internal and administrative endpoints had different security scheme references — a detail that indicated they used a different authentication path that was worth examining separately.
What the Second and Third Specs Added
The second specification file, found on a different API host, described the company's infrastructure management API — the interface used by the platform itself to manage the underlying compute and networking infrastructure.
This was more sensitive than the first. The spec described operations for:
- Assigning physical resources to customer accounts
- Modifying network routing configurations at the infrastructure level
- Querying internal capacity metrics and allocation data
- Triggering maintenance operations on hardware components
These were not customer-facing operations. They were the internal mechanisms that the customer-facing API called behind the scenes. The fact that their specification was accessible from the public internet indicated that the infrastructure management API host had been misconfigured to share its documentation endpoint with the customer-facing API tier's network exposure.
The third specification, smaller than the others, described a monitoring and alerting API. Its value was less in its operations than in its data model: the spec's response schemas documented internal metric names, alert threshold identifiers, and service dependency mappings that described how the platform's components interacted with each other.
Reading three spec files in sequence gave a picture of the platform's internal architecture — how customer requests flowed through the system, which internal services handled which operations, and which endpoints bridged the customer-facing and internal-facing tiers.
Converting Specification into Test Cases
An OpenAPI spec transforms API testing from exploration into verification. Without the spec, finding an undocumented administrative endpoint requires fuzzing known paths, guessing parameter names from response behavior, and spending hours mapping an API surface that might be hundreds of endpoints deep. With the spec, the endpoint inventory is complete and the parameter schemas are exact.
From the three specifications, I built a targeted test plan:
Administrative endpoints marked as restricted. The spec identified which endpoints were annotated as admin-only or internal-use. These became the first test targets: did they enforce the described access controls against a standard customer account, or did they accept requests that they should have rejected?
Parameter variants with unusual behavior. Fields annotated as internal-use or described as bypassing normal processing logic — like the override_billing_cycle parameter — warranted direct testing to confirm they were inaccessible or inoperative from external callers.
The internal service endpoints. The /internal/ prefixed endpoints in the first spec were directly testable. Sending authenticated requests to these endpoints from an external client would either reveal a missing authorization check or confirm that a separate layer of network access control restricted them correctly.
Cross-spec endpoint relationships. Operations visible in the infrastructure management spec that corresponded to operations in the customer-facing spec provided test cases for privilege boundary enforcement: did the customer API's calls into the infrastructure API enforce appropriate limits, or was there a way to influence infrastructure-level operations through customer-facing parameters?
Some of these tests returned 403 or 404 responses, confirming that access controls were enforced at the application layer. Others returned unexpected results — responses that indicated the endpoint accepted the request but with unexpected output, or parameter fields that had effects they should not have had from external callers.
The findings from those tests are separately documented. The specification exposure itself was the enabler, not the vulnerability.
Why the Specs Were There
Working through the infrastructure that served the specification files, the pattern was consistent with a common failure mode: documentation endpoints enabled by default in the API framework used to build each service, never explicitly disabled in the deployment configuration.
Each service was built using a framework that, out of the box, exposes a documentation endpoint when API annotations are present. The endpoint is intended for development and testing — it is how developers interact with an API they are actively building before the formal documentation is written. Disabling it in production requires an explicit configuration change.
The deployment pipeline for each service did not include that configuration change. The framework's default behavior carried through from development to production without any step that evaluated whether documentation exposure was appropriate.
The scope of the exposure reflected the scope of the gap. Three separate services, three separate teams, three separate deployment pipelines — each with the same omission. Not a single mistake that was made once, but a systematic absence in the deployment process that was repeated for every service that used the same framework.
Remediation
The remediation was straightforward to specify and implement:
Disable documentation endpoints in production. Each framework had a configuration setting that disabled the OpenAPI endpoint. Applying it to production deployment configurations removed the exposure. Development and staging environments retained the endpoint since it remains useful there.
Scope documentation to public APIs only. For services with genuinely public APIs, documentation should be served only for the public-facing subset of endpoints — not for administrative, internal, or infrastructure-facing operations. Generating a separate spec that includes only the appropriate scope, rather than serving the full machine-generated spec, prevents information disclosure even when documentation is intentionally public.
Include documentation endpoint status in deployment review. Adding a documentation endpoint check to the deployment checklist — alongside other pre-deployment validations — ensures that future services are reviewed for this before they reach production.
Network access controls for internal service APIs. Endpoints documented as internal-service-to-service communication should be accessible only from internal network segments, not from the public internet. The infrastructure management API's specification exposure indicated a network boundary issue in addition to the documentation configuration issue.
The Understated Risk of Specification Exposure
Organizations that accept OpenAPI specification exposure as a low-severity finding typically underestimate it on the basis that the spec does not directly grant access to anything. Accessing a spec does not authenticate a request. It does not bypass a permission check.
What it does is eliminate the work of discovery. The difference between an attacker who has to enumerate a 400-endpoint API through probing and one who has the full spec in hand is the difference between a month of manual testing and an afternoon. Every endpoint, every parameter, every security scheme, every developer annotation is immediately available.
For a determined attacker, the spec also surfaces the most interesting targets. The annotations that say "admin-only" or "internal-use" or "bypasses normal validation" are written by developers who understand what the endpoint does. An attacker reading those descriptions understands the same thing — and knows exactly where to probe first.
The value of the specification exposure finding is not in what it directly enables. It is in the audit trail it provides for everything else: a complete map of what was tested, what the application claims to do, and what gaps might exist between the documented behavior and the enforced behavior.
For a deeper look at the CORS misconfiguration that appeared alongside this finding during the same assessment, see the CORS misconfiguration knowledge article. For the full range of API information disclosure patterns, see the source map exposure article.