API Security Testing Checklist for 2026
API vulnerabilities top the OWASP list for good reason — APIs expose your data model directly. This checklist covers the ten categories that account for the majority of exploitable API findings: JWT attacks, IDOR/BOLA, mass assignment, injection, rate limiting, CORS, and GraphQL-specific vectors.
Authentication
JWT alg:none remains exploitable in unpatched libraries. Always enforce algorithm allowlisting server-side — never trust the alg header from the client.
- JWT algorithm is allowlisted server-side (
RS256orHS256only — nevernone) - JWT signature verification is enforced on every protected endpoint
- JWT expiration (
expclaim) is validated; tokens are not accepted indefinitely - JWT secret rotation is documented and tested
- OAuth2 authorization code flow uses
stateparameter to prevent CSRF - OAuth2
redirect_uriis validated against a strict allowlist (no open redirect) - OAuth2 PKCE is enforced for public clients (SPAs, mobile apps)
- API keys are not transmitted in URL query parameters (they appear in logs)
- Bearer tokens are not logged in application logs or access logs
- Password reset tokens are single-use and expire within 15 minutes
Authorization (IDOR / BOLA)
IDOR is the most common critical API finding. If your endpoint accepts an ID parameter and returns data, it must verify that the caller owns that resource — every time, at every layer.
- Every endpoint that accepts a resource identifier validates ownership against the authenticated user
- UUID identifiers are used instead of sequential integers (reduces enumeration, does not replace auth checks)
- Admin endpoints are separated from user endpoints and gated at the infrastructure level
- Horizontal privilege escalation is tested: can User A access User B's data using their own valid token?
- Vertical privilege escalation is tested: can a standard user reach admin-only endpoints?
- GraphQL queries with nested resolvers enforce authorization at each resolver level, not just the root
Input Validation and Injection
- All query parameters and request body fields are validated against an explicit schema (length, type, format)
- SQL queries use parameterized statements; ORM raw query escaping is audited
- NoSQL injection vectors are tested for MongoDB (
$where,$regex), ElasticSearch (_search), and RedisEVAL - Command injection is tested for any endpoint that shells out (
exec,spawn,system) - SSTI (Server-Side Template Injection) is tested on endpoints that render user-supplied content
- XML input is parsed with external entity resolution disabled (
FEATURE_SECURE_PROCESSING) - File upload endpoints validate MIME type server-side (not just client-side), check magic bytes, and restrict execution paths
Mass Assignment
Mass assignment is frequently introduced silently when new fields are added to a model. An allowlist of accepted fields should be enforced at the deserialization layer, not just the database layer.
- Request deserialization uses an explicit allowlist of accepted fields (
role,is_admin,creditsmust not be settable by clients) - Pydantic / Zod / Joi schemas reject unknown fields by default
- Privileged fields (
role,verified,balance,permissions) are never updated from client-supplied JSON - Object creation and update endpoints are tested with extra fields beyond the documented schema
Rate Limiting and Abuse Prevention
- Authentication endpoints (login, password reset, MFA verification) are rate-limited per IP and per account
- Credential stuffing protection is in place (rate limit + CAPTCHA on login after N failures)
- API keys have per-key rate limits; limits are enforced at the gateway, not the application layer
- Bulk endpoints (batch operations, exports) have size and rate limits
- GraphQL query depth and complexity limits are enforced
CORS Configuration
-
Access-Control-Allow-Originis not set to*for endpoints that use cookies or authorization headers - CORS allowlist is explicit (not
null, not wildcard with credentials enabled) - Preflight responses do not expose sensitive headers to cross-origin callers
- CORS misconfiguration is tested from an external origin in staging before production deploy
GraphQL-Specific Vectors
- Introspection is disabled in production (or gated behind authentication)
- Batching attacks are tested: sending 100+ queries in a single request to bypass rate limits
- Alias attacks are tested: using GraphQL aliases to repeat expensive operations
- Query depth limiting is enforced (default max 7–10 levels)
- Mutations that modify sensitive data require re-authentication or CSRF protection
- Subscription endpoints are authenticated and scoped to the authenticated user's data
Reporting and Monitoring
- API errors return generic messages to clients; stack traces and SQL errors are never exposed
- Every authenticated action is logged with user ID, resource ID, and timestamp
- Anomalous access patterns (high-volume reads, cross-account access) generate alerts
- Security-relevant events (auth failures, permission denials, large data exports) are in a separate audit log