API Security Testing Checklist
A systematic checklist for testing API security covering authentication, authorization, rate limiting, input validation, error handling, CORS, TLS enforcement, and versioning with practical curl and httpie command examples.
APIs are the primary attack surface for modern applications. As explored in API Security Beyond Status Codes, unlike browser-rendered pages, APIs are designed for programmatic access, which means attackers can interact with them directly using simple HTTP clients. A systematic security testing checklist ensures you cover the critical areas that automated scanners frequently miss. Use this guide alongside CyberShield scan results to build a complete picture of your API's security posture.
1. Authentication Testing
Authentication flaws let attackers impersonate legitimate users. Test each mechanism your API supports.
JWT Validation
Verify that the API rejects tampered and expired tokens:
# Send a request with no token — should return 401
curl -s -o /dev/null -w "%{http_code}" https://api.example.com/users/me
# Send a request with an expired token
curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer eyJhbGciOiJub25lIn0.eyJzdWIiOiIxMjM0NTY3ODkwIn0." https://api.example.com/users/me
# Send a token with "alg": "none" — must be rejected
curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $(echo -n '{"alg":"none","typ":"JWT"}' | base64 -w0).$(echo -n '{"sub":"admin"}' | base64 -w0)." https://api.example.com/users/me
The alg: none attack is critical. If the API accepts it, an attacker can forge tokens for any user without knowing the signing key.
API Key Security
Ensure API keys are transmitted securely and that revoked keys are rejected:
# Test with a revoked or invalid key — should return 401 or 403
curl -s -o /dev/null -w "%{http_code}" -H "X-API-Key: revoked_key_value" https://api.example.com/data
# Verify the key is not accepted in URL parameters (leaks in logs)
curl -s -o /dev/null -w "%{http_code}" "https://api.example.com/data?api_key=your_key"
API keys in URL query parameters appear in server access logs, browser history, and CDN logs. Always require keys in headers.
OAuth Token Handling
Verify that access tokens have appropriate scope restrictions:
# Use a read-only scoped token to attempt a write operation — should return 403
curl -s -o /dev/null -w "%{http_code}" -X POST -H "Authorization: Bearer READ_ONLY_TOKEN" -H "Content-Type: application/json" -d '{"name":"test"}' https://api.example.com/resources
2. Authorization Checks (BOLA/IDOR)
Broken Object Level Authorization (BOLA), also known as Insecure Direct Object Reference (IDOR), is the number one API vulnerability according to the OWASP API Security Top 10. Test by accessing resources belonging to other users:
# Authenticate as User A, then request User B's data
curl -s -w "\n%{http_code}" -H "Authorization: Bearer USER_A_TOKEN" https://api.example.com/users/USER_B_ID/profile
# Test with sequential IDs — increment through numeric identifiers
for id in $(seq 1 10); do
echo "ID $id: $(curl -s -o /dev/null -w '%{http_code}' -H 'Authorization: Bearer USER_A_TOKEN' https://api.example.com/orders/$id)"
done
Every endpoint that accepts a resource identifier must verify that the authenticated user has permission to access that specific resource. A 200 response for another user's data confirms a BOLA vulnerability.
3. Rate Limiting Verification
APIs without rate limiting are vulnerable to brute force, credential stuffing, and denial of service:
# Send 50 rapid requests to a login endpoint and watch for 429 responses
for i in $(seq 1 50); do
echo "Request $i: $(curl -s -o /dev/null -w '%{http_code}' -X POST -H 'Content-Type: application/json' -d '{"email":"test@example.com","password":"wrong"}' https://api.example.com/auth/login)"
done
# Check for rate limit headers in the response
curl -sI -X POST -H "Content-Type: application/json" -d '{"email":"test@example.com","password":"test"}' https://api.example.com/auth/login | grep -iE '(x-ratelimit|retry-after)'
Look for X-RateLimit-Limit, X-RateLimit-Remaining, and Retry-After headers. Their absence on sensitive endpoints like login, registration, and password reset is a finding.
4. Input Validation
Test that the API rejects malformed and malicious input rather than processing it:
# SQL injection in a query parameter
curl -s -o /dev/null -w "%{http_code}" "https://api.example.com/search?q=' UNION SELECT * FROM users--"
# Oversized payload — test for lack of body size limits
python3 -c "print('{\"name\":\"' + 'A'*1000000 + '\"}')" | curl -s -o /dev/null -w "%{http_code}" -X POST -H "Content-Type: application/json" -d @- https://api.example.com/resources
# Type confusion — send a string where a number is expected
curl -s -w "\n%{http_code}" -X POST -H "Content-Type: application/json" -d '{"quantity":"not_a_number","price":-1}' https://api.example.com/orders
The API should return 400 with a descriptive error for invalid input. Negative values in financial fields, excessively long strings, and unexpected types should all be rejected.
5. Error Handling Review
Verbose error messages leak implementation details that help attackers craft targeted exploits:
# Request a nonexistent endpoint — check for stack traces
curl -s https://api.example.com/nonexistent_endpoint_12345
# Trigger a server error with malformed JSON
curl -s -X POST -H "Content-Type: application/json" -d '{invalid json' https://api.example.com/resources
# Check for technology disclosure in headers
curl -sI https://api.example.com/ | grep -iE '(x-powered-by|server|x-aspnet)'
Production APIs should return generic error messages ({"error": "Internal server error"}) with no stack traces, SQL queries, or file paths. The X-Powered-By and Server headers should be removed or minimized.
6. CORS Configuration
Misconfigured CORS can allow malicious websites to make authenticated requests to your API:
# Test with a malicious origin — should NOT be reflected
curl -sI -H "Origin: https://evil.com" https://api.example.com/data | grep -i "access-control"
# Test with null origin — should be rejected
curl -sI -H "Origin: null" https://api.example.com/data | grep -i "access-control"
# Check if credentials are allowed with wildcard origin (dangerous)
curl -sI -H "Origin: https://anything.com" https://api.example.com/data | grep -iE "(access-control-allow-origin|access-control-allow-credentials)"
If Access-Control-Allow-Origin reflects any origin while Access-Control-Allow-Credentials: true is set, any website can make authenticated cross-origin requests to your API. This is closely related to CSRF protection -- both address the risk of unauthorized cross-origin actions.
7. TLS Enforcement
All API traffic must be encrypted. Test that HTTP is properly redirected or rejected:
# Test HTTP access — should redirect to HTTPS or refuse connection
curl -s -o /dev/null -w "%{http_code}" http://api.example.com/data
# Check for HSTS header
curl -sI https://api.example.com/ | grep -i "strict-transport-security"
# Verify TLS version — reject TLS 1.0 and 1.1
curl -s --tlsv1.0 --tls-max 1.0 https://api.example.com/ 2>&1 | head -5
The HSTS header should include max-age of at least 31536000 (one year). Connections using TLS 1.0 or 1.1 should fail. For a complete list of recommended headers and their configurations, see the HTTP security headers implementation guide.
8. API Versioning Security
Older API versions may lack security patches applied to current versions:
# Test deprecated API versions — they may bypass newer auth requirements
curl -s -o /dev/null -w "%{http_code}" https://api.example.com/v1/admin/users
curl -s -o /dev/null -w "%{http_code}" https://api.example.com/v2/admin/users
# Check if unversioned endpoints exist
curl -s -o /dev/null -w "%{http_code}" https://api.example.com/admin/users
Deprecated API versions should return 410 Gone or redirect to the current version. Leaving old versions active with weaker security controls is a common oversight.
Verification
Work through this checklist against your API endpoints and document each result. Cross-reference with CyberShield scan findings to identify gaps -- the automated scan covers TLS, headers, and CORS configuration, while this manual checklist covers application-layer logic that requires authenticated context. Retest after remediation to confirm each issue is resolved.
Continue Reading
API Security Assessment: Beyond REST Status Codes
APIs are the fastest-growing attack surface in modern applications. Learn why status codes alone miss critical vulnerabilities and how to assess authentication, rate limiting, JWT configuration, and endpoint exposure.
Lessons from Supply Chain Attacks: What External Scanning Would Have Caught
Supply chain attacks exploit trusted relationships between organizations and their vendors. Learn how external security assessment provides early warning signs and reduces supply chain risk through continuous vendor monitoring.
Third-Party Vendor Risk Assessment Without a Pentest
You don't need a penetration test to evaluate a vendor's security posture. External security assessment provides objective, non-intrusive insight into how well third parties protect their internet-facing infrastructure.