| name | api-security-checklist |
| description | Checklist for passive API security assessment. Covers endpoint discovery, CORS, rate limiting, authentication, GraphQL, and response security. |
| allowed-tools | Read, Grep, Glob, Bash(curl:*), Bash(grep:*), Bash(head:*), Bash(tail:*), Bash(echo:*), Bash(cat:*), Bash(base64:*), Bash(jq:*), mcp__plugin_playwright_playwright__browser_navigate, mcp__plugin_playwright_playwright__browser_snapshot, mcp__plugin_playwright_playwright__browser_evaluate, mcp__plugin_playwright_playwright__browser_network_requests, mcp__plugin_playwright_playwright__browser_run_code, mcp__plugin_playwright_playwright__browser_close |
API Security Checklist
Comprehensive, actionable checklist for passive API security scanning. All checks are non-destructive and safe for production environments. Replace TARGET with the actual target domain (no trailing slash).
1. Endpoint Discovery
How to find API endpoints:
- Analyze JS bundles with Playwright: search for URL patterns (
/api/, /v1/, /graphql, fetch/axios calls)
- Check network requests via Playwright
browser_network_requests
- Probe common API paths:
for path in /api /api/v1 /api/v2 /graphql /swagger.json /swagger-ui.html /openapi.json /api-docs /api-docs.json /.well-known/openid-configuration /health /status /metrics /actuator; do
code=$(curl -sI "https://TARGET${path}" -o /dev/null -w "%{http_code}")
echo "$code $path"
done
Playwright snippet for JS endpoint extraction:
const scripts = Array.from(document.querySelectorAll('script'));
const inlineCode = scripts.filter(s => !s.src).map(s => s.textContent).join('\n');
const apiPatterns = inlineCode.match(/["'](\/api\/[^"']+|\/v[0-9]+\/[^"']+|\/graphql[^"']*)/g);
2. CORS Analysis
Test CORS configuration:
curl -sI -H "Origin: https://evil.com" https://TARGET/api/ | grep -i "access-control"
curl -sI -H "Origin: null" https://TARGET/api/ | grep -i "access-control"
Misconfigurations to flag:
Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true (Critical)
- Origin reflection (reflects any Origin back) (Critical)
- Null origin allowed with credentials (High)
- Overly permissive wildcard without credentials (Medium)
- Missing CORS headers entirely on API (Info - may be intentional)
3. Rate Limiting
Check for rate-limiting headers:
curl -sI https://TARGET/api/ | grep -i "x-ratelimit\|ratelimit\|retry-after\|x-rate-limit"
Test with rapid requests (5 requests, observe responses):
for i in 1 2 3 4 5; do
curl -sI https://TARGET/api/ -o /dev/null -w "%{http_code} "
done
echo ""
Missing rate limiting: High for auth endpoints, Medium for other endpoints.
4. Authentication Analysis
Passive checks:
- Endpoints accessible without auth: try accessing API endpoints without Authorization header
- Token exposure: check if JWT/Bearer tokens appear in URLs or query strings
- JWT analysis (decode header, check alg):
echo "HEADER_PART" | base64 -d 2>/dev/null
- Check for
alg: none, alg: HS256 with known weak secrets
5. GraphQL Security
Introspection query:
curl -s -X POST https://TARGET/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{ __schema { types { name } } }"}'
curl -s "https://TARGET/graphql?query=\{__schema\{types\{name\}\}\}"
Check for:
- Open introspection (High - exposes full API schema)
- Verbose error messages with field suggestions
- No query depth/complexity limiting (observe only)
- Batch queries enabled
6. Response Security
For each discovered API endpoint, check:
- Security headers on API responses (same as web security but on API routes)
- Verbose error messages (stack traces, SQL errors, internal paths)
- Version info in responses (X-Powered-By, Server, custom version headers)
- Sensitive data in responses (PII, internal IDs, debug info)
- Content-Type header matches actual content
- Response includes more data than needed (over-fetching)
curl -s https://TARGET/api/non-existent-endpoint
curl -s -X POST https://TARGET/api/ -H "Content-Type: application/json" -d '{invalid}'
7. API Versioning & Documentation Exposure
- Check if old API versions still accessible (v1 vs v2)
- Swagger/OpenAPI docs publicly accessible (may expose internal endpoints)
- API documentation without authentication
Severity Assessment Guide
| Finding | Severity |
|---|
| CORS wildcard with credentials | Critical |
| Open GraphQL introspection | High |
| No rate limiting on auth endpoints | High |
| API endpoints without authentication | High (context-dependent) |
| JWT with alg:none | Critical |
| Swagger/API docs publicly exposed | Medium |
| Version info in headers | Low |
| Verbose error responses | Medium |
| No rate limiting on public endpoints | Medium |
| Old API versions still accessible | Low |
Finding Report Format
Each finding MUST follow this format:
### [SEVERITY] Problem title
- **URL/Evidence:** specific URL, header, code fragment
- **Risk:** technical + business risk description
- **Recommendation:** what to do (with config/code example)
- **Verification:** how to confirm the fix
- **Owner:** Dev / DevOps / Security