Swagger and OpenAPI Security Testing: Finding Vulnerabilities via API Specs
An exposed OpenAPI specification is a complete map of your API surface. Every endpoint, every parameter, every authentication requirement — documented and machine-readable. For legitimate users, this is convenience. For a security tester (or an attacker), it is reconnaissance that would otherwise take hours condensed into a single JSON file.
This guide covers how to find OpenAPI and Swagger specifications on your targets, what to look for when you have one, how to use the spec to drive security testing at scale, and the specific vulnerability classes that appear most consistently when API documentation is used as a testing guide.
Finding API Specifications
Many applications expose their API specs without authentication — either intentionally (public developer documentation) or by accident (internal APIs deployed with default settings). Common locations:
# OpenAPI v3 common paths
/openapi.json
/openapi.yaml
/api/openapi.json
/v1/openapi.json
/v2/openapi.json
/api-docs
/api-docs.json
/api/v1/api-docs
# Swagger v2 common paths
/swagger.json
/swagger.yaml
/swagger/v1/swagger.json
/swagger/v2/swagger.json
/api/swagger.json
/api/swagger
/swagger-ui.html
/swagger-ui/
/swagger-ui/index.html
# Framework-specific defaults
/v2/api-docs # Spring Boot (springdoc-openapi)
/v3/api-docs # Spring Boot (springdoc-openapi v3)
/__swagger__/
/redoc
/rapidoc
# Developer portals
/developer
/developer/api
/docs/api
/api-reference
Use a tool like ffuf or dirsearch with an API-focused wordlist to automate discovery:
ffuf -u https://target.com/FUZZ -w api-spec-paths.txt -mc 200,301,302 -t 50
# Or with curl — test common paths in a loop:
for path in swagger.json openapi.json api-docs v3/api-docs swagger/v1/swagger.json; do
status=$(curl -s -o /dev/null -w "%{http_code}" https://target.com/$path)
echo "$status $path"
done
Analysing the Specification
Extracting All Endpoints
Once you have the spec, extract every endpoint and method combination. This gives you a definitive list of attack surface:
import json, sys
with open('openapi.json') as f:
spec = json.load(f)
for path, methods in spec.get('paths', {}).items():
for method, details in methods.items():
auth = 'security' in details or 'security' in spec
print(f"{method.upper():8} {path:50} auth={auth}")
# With jq from the command line:
cat openapi.json | jq -r '.paths | to_entries[] | .key as $path | .value | to_entries[] | "\(.key | ascii_upcase) \($path)"'
Security Schemes and Authentication Gaps
The spec's securitySchemes and per-endpoint security definitions reveal what authentication is supposed to be required. Mismatches between documented requirements and actual enforcement are common:
# Check which endpoints have no security requirement defined
cat openapi.json | jq -r '
.paths | to_entries[] |
.key as $path |
.value | to_entries[] |
select(.value.security == null or .value.security == []) |
"\(.key | ascii_upcase) \($path) — NO SECURITY DEFINED"
'
Look specifically for:
- Admin endpoints (
/admin,/internal,/management) with no security requirement - Bulk operations (batch delete, export all) without rate limiting annotations
- Endpoints that accept file uploads without documented restrictions
- Schema definitions with no
maxLengthorpatternconstraints — injection targets
Testing with the Specification as a Guide
Authentication Bypass Testing
For every endpoint that requires authentication per the spec, test without credentials and with invalid credentials:
#!/bin/bash
# Extract authenticated endpoints and test unauthenticated
BASE="https://target.com"
TOKEN="your_valid_token"
# Test without token
curl -s -o /dev/null -w "%{http_code} GET /api/users/me\n" $BASE/api/users/me
# Expect: 401 or 403
# Test with tampered token
curl -s -H "Authorization: Bearer invalid.token.here" \
-o /dev/null -w "%{http_code} GET /api/users/me (bad token)\n" \
$BASE/api/users/me
# Expect: 401
Parameter Fuzzing with Schema Information
The schema definitions tell you exactly what input the API expects — which is exactly what to violate during security testing:
# If spec defines: username: {type: string, maxLength: 20}
# Test with 21 characters, then 1000 characters, then injection payloads
# If spec defines: age: {type: integer, minimum: 0, maximum: 150}
# Test with -1, 0, 151, 999999, "string", null, []
# If spec defines: role: {type: string, enum: ["user", "admin"]}
# Test with "superadmin", "root", null, and missing the field entirely
Tools that automate spec-driven fuzzing:
## schemathesis — spec-driven property-based testing
pip install schemathesis
schemathesis run https://target.com/openapi.json --auth "Bearer $TOKEN"
# Or against a local spec with custom target:
schemathesis run openapi.json --base-url https://target.com/api --auth "Bearer $TOKEN"
## RESTler — intelligent REST API fuzzing from Microsoft Research
# Generates test sequences from OpenAPI specs
./Restler compile --api_spec openapi.json
./Restler fuzz --grammar_file Compile/grammar.py --target_ip target.com --target_port 443
Information Disclosure in API Specs
Beyond using the spec as a testing guide, the spec itself is a finding when exposed without authentication. Review it for:
Internal Infrastructure References
# Servers object may reveal internal hostnames
cat openapi.json | jq '.servers'
# Look for internal URLs in examples, descriptions, or x- extensions
cat openapi.json | grep -E "(internal|localhost|10\.|192\.168\.|172\.|\.internal|\.corp)"
Sensitive Data Schemas
# Schema property names reveal data model
cat openapi.json | jq -r '.. | .properties? // empty | keys[]' | sort -u | \
grep -iE "(password|secret|token|key|ssn|credit|card|cvv|pin|dob|salary)"
Deprecated Endpoints Still Active
# Find deprecated endpoints in spec
cat openapi.json | jq -r '
.paths | to_entries[] |
.key as $path |
.value | to_entries[] |
select(.value.deprecated == true) |
"\(.key | ascii_upcase) \($path)"
'
# Then test if deprecated endpoints still respond
# Deprecated ≠ removed; they often have weaker controls
BOLA/IDOR via Spec Analysis
OpenAPI specs reveal object identifier patterns used in paths. These are direct tests for broken object-level authorization (BOLA/IDOR):
GET /api/users/{userId}/documents/{documentId}
GET /api/orders/{orderId}
GET /api/invoices/{invoiceId}/download
POST /api/admin/users/{userId}/disable
For every endpoint with a path parameter referencing an object ID:
- Authenticate as User A and create or retrieve a resource — get its ID
- Authenticate as User B
- Attempt to access User A's resource using User B's credentials
- Check for cross-tenant access (if multi-tenant)
- Test sequential IDs, GUIDs, and other ID patterns visible in the spec
Mass Assignment from Schema Definitions
Request body schemas list every accepted property. Compare the documented writable properties against what the server actually processes:
# If POST /api/users schema includes: {name, email, role, isAdmin}
# But the application should only accept {name, email} from regular users
# Test sending role=admin or isAdmin=true in the request body
curl -X POST https://target.com/api/users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $USER_TOKEN" \
-d '{"name": "Test", "email": "test@test.com", "role": "admin", "isAdmin": true}'
API Version Testing
When a spec defines multiple server versions or you find versioned paths, older versions are high-value targets:
GET /api/v1/admin/users # May lack auth checks added in v2
GET /api/v2/admin/users # Current version with proper controls
GET /v1/openapi.json # Old spec may document removed endpoints
# Test if v1 endpoints accept v2 tokens and bypass v2 controls
# Test if deprecated v1 endpoints still respond with reduced security
# Check if v1 returns more fields in responses (information disclosure)
Importing Specs into Testing Tools
| Tool | How to Import OpenAPI Spec | Use Case |
|---|---|---|
| Burp Suite | Target → Site Map → right-click → OpenAPI definition | Auto-populate site map and scanner with all endpoints |
| Postman | Import → OpenAPI 3.0 or Swagger 2.0 | Generate collection for manual testing |
| OWASP ZAP | Import → OpenAPI Definition | Spider entire API surface, run active scan |
| schemathesis | CLI: schemathesis run openapi.json |
Property-based fuzzing of all endpoints |
| Nuclei | nuclei -u target.com -t openapi.yaml |
Template-based testing of spec-defined endpoints |
Ironimo automatically discovers OpenAPI and Swagger specifications during scanning, uses them to enumerate and test every documented endpoint, and identifies discrepancies between what the spec claims is protected and what the API actually enforces. The spec is a map — Ironimo uses it as one.
Start free scan