StackPractices
intermediate By Mathias Paulenko

API Security Review Template (OWASP Checklist)

A fillable checklist template for reviewing API authentication, authorization, rate limiting, and OWASP API Security Top 10 coverage.

Topics: security

Overview

An API security review is a structured audit of how an API handles authentication, authorization, input, and abuse — before and after it ships. A single missing owner check or unvalidated input can expose customer data or allow account takeover, and those are exactly the gaps automated scanners keep missing. This template is a fillable checklist: copy it into a ticket, work through it per API, and keep the completed review as audit evidence. Each section maps to the OWASP API Security Top 10 (2023), so the well-known failure modes are covered by construction.

When to Use

  • Before releasing a new public or partner-facing API to production.
  • During a quarterly security audit of existing APIs.
  • After a security incident, a major dependency upgrade, or an infrastructure change.
  • When onboarding a new service that consumes or exposes APIs.
  • When a compliance framework (SOC 2, ISO 27001) asks for documented security reviews.

The checklist isn’t a substitute for a penetration test — it catches misconfigurations and known omissions, not novel vulnerabilities. For a control-by-control walkthrough, see the API Security Checklist guide.

Solution

# API Security Review: `<API Name>`

## 1. Metadata

| Field | Value |
|-------|-------|
| API Name | `name` |
| Version | `v1.0.0` |
| API Type | `REST / GraphQL / gRPC / WebSocket` |
| Exposure | `Internal / Partner / Public` |
| Auth Type | `OAuth2 / API Key / mTLS / None` |
| Security Owner | `@name` |
| Review Date | `YYYY-MM-DD` |

## 2. Authentication

- [ ] All endpoints require authentication except explicitly documented public ones
- [ ] OAuth2/OIDC tokens arrive via `Authorization: Bearer`; state, PKCE, and redirect URI allowlist enforced
- [ ] API keys sent in `X-Api-Key` header — never in query params
- [ ] API keys rotated every 90 days and stored in a secrets manager
- [ ] Access tokens expire in under 1 hour; refresh tokens rotate on each use and are revocable
- [ ] JWT validated: signature, expiry, issuer, audience
- [ ] MFA required for admin and other sensitive operations
- [ ] mTLS enforced for service-to-service communication in production
- [ ] Credentials never logged, returned in errors, or stored in URLs

## 3. Authorization

- [ ] Access control checks the resource owner, not just authentication status (BOLA/IDOR)
- [ ] Horizontal access control: User A can't read User B's `/users/{id}` data
- [ ] Vertical access control: admin endpoints reject non-admin tokens
- [ ] Role/permission claims validated server-side — never trusted from the client
- [ ] List and search endpoints scope results to the current caller
- [ ] Sub-resources inherit parent permissions (e.g., `/orders/{id}/items`)
- [ ] Every sensitive action audited (create, delete, bulk data access)
- [ ] No auth bypass via path traversal or HTTP method override

## 4. Input Validation

- [ ] All inputs validated against a strict schema (OpenAPI, JSON Schema)
- [ ] Payloads with wrong types rejected — not silently coerced
- [ ] Max payload size enforced at the gateway (e.g., 1 MB); limits on string, array, and nesting depth
- [ ] Content-Type header checked against the actual body
- [ ] Parameterized queries or ORM only — no string concatenation into SQL
- [ ] Path parameters validated against expected patterns (UUID, slug, numeric)
- [ ] File uploads restricted to an allowlist of names and MIME types, malware-scanned
- [ ] SSRF: outbound requests validated against a domain allowlist

## 5. Rate Limiting & Abuse Prevention

| Client Type | Limit | Window | On Exceed |
|-------------|-------|--------|-----------|
| Unauthenticated | 60 req/min | 1 min | 429 + `Retry-After` |
| Authenticated | 1,000 req/min | 1 min | 429 + `Retry-After` |
| Premium | 10,000 req/min | 1 min | Graduated throttling |

- [ ] Rate limits defined per consumer ID and per endpoint — not global, not IP-only
- [ ] Rate limit headers on every response (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)
- [ ] Volumetric DDoS handled at CDN/WAF layer
- [ ] Account lockout after N failed authentication attempts

## 6. Secrets Management

- [ ] No credentials, tokens, or signing keys in source code
- [ ] Secrets injected via environment variables or a secrets manager (Vault, AWS Secrets Manager)
- [ ] JWT signing keys rotated periodically with overlap for old tokens
- [ ] Logs contain no tokens, passwords, or card numbers

## 7. Data Protection & Output

- [ ] No sensitive data in responses (passwords, tokens, unnecessary PII)
- [ ] TLS 1.2+ in transit with HSTS; AES-256 at rest
- [ ] Response fields filtered by caller role — no mass assignment reads
- [ ] CORS explicit allowlist — no wildcard `*` with credentials
- [ ] `Cache-Control: no-store` on responses carrying sensitive data
- [ ] Security headers: `X-Content-Type-Options: nosniff`, CSP `frame-ancestors` where HTML is served
- [ ] PII masked or tokenized in logs

## 8. Error Handling & Logging

- [ ] Error responses don't leak stack traces, SQL, or internal paths
- [ ] Auth failures return generic messages (no user enumeration)
- [ ] Every request logs: timestamp, client ID, endpoint, method, status code, latency
- [ ] Failed authentication attempts logged with IP and timestamp
- [ ] Logs forwarded to a SIEM with tamper protection; retention ≥ 90 days
- [ ] Anomaly monitoring for traffic spikes and scraping patterns

## 9. OWASP API Security Top 10 (2023) Coverage

| Risk | Check | Status |
|------|-------|--------|
| API1 Broken Object Level Authorization | Owner check on every object endpoint | Pass / Fail |
| API2 Broken Authentication | Token validation, brute-force protection | Pass / Fail |
| API3 Broken Object Property Level Authorization | Response field filtering, no mass assignment | Pass / Fail |
| API4 Unrestricted Resource Consumption | Rate limits, payload caps, timeouts | Pass / Fail |
| API5 Broken Function Level Authorization | Admin functions reject non-admin callers | Pass / Fail |
| API6 Unrestricted Access to Sensitive Business Flows | Anti-automation on signup/purchase flows | Pass / Fail |
| API7 Server Side Request Forgery | Outbound URL allowlist, cloud metadata blocked | Pass / Fail |
| API8 Security Misconfiguration | No default credentials, hardened TLS | Pass / Fail |
| API9 Improper Inventory Management | Deprecated versions sunset, undocumented endpoints audited | Pass / Fail |
| API10 Unsafe Consumption of APIs | Third-party responses validated, upstream TLS verified | Pass / Fail |

## 10. Findings & Sign-off

| # | Finding | Severity | Owner | Due | Status |
|---|---------|----------|-------|-----|--------|
| 1 | | | | | |

| Field | Value |
|-------|-------|
| Reviewer | `@name` |
| Second reviewer | `@name` (required for public APIs) |
| Result | `Approved / Approved with exceptions / Blocked` |
| Next review | `YYYY-MM-DD` |

How to Run the Review

  1. Scope the API. List its endpoints from the OpenAPI spec or gateway config and mark each as public, partner, or internal — exposure decides how deep each section goes.
  2. Fill the checklist. Work through it per API or per endpoint group. An unchecked box isn’t a failure, it’s a documented risk — each one becomes a remediation ticket.
  3. Score the findings with the severity table below so fixes land in the right order.
  4. Remediate and re-check. Rerun the failed sections once fixes ship, and retest the full checklist within 30 days of any security incident.
  5. Archive the completed review with date and reviewer. Auditors ask for evidence, not intentions.

For a narrower scope — one PR that touches an auth path — the security review checklist for PRs is a better fit than this full pass.

Scoring Findings

Every unchecked box is a risk the team chose to accept or fix. Suggested triage:

SeverityExamplesAction
BlockerAuth bypass, BOLA on production data, injection, secrets in code or logsFix before release
HighNo rate limits on public endpoints, weak token validation, missing TLSFix within the sprint
MediumMissing security headers, verbose errors, undocumented endpointsSchedule and track
LowDocumentation gaps, non-critical hardeningBacklog with an owner

Unresolved blockers and highs need a written exception — owner, residual risk, and a deadline. Track them the same way you track CVEs; a vulnerability management process keeps accepted risks from becoming forgotten risks.

Explanation

The checklist is organized as defense in depth: a request crosses the CDN/WAF (volumetric attacks), the gateway (rate limits, authentication), the service (authorization at object level), input validation, and finally the data layer (encryption, filtered output). Most API breaches trace back to a single skipped layer — usually authorization, because teams verify who is calling but never whether that caller may see this object. That’s BOLA, and it sits at API1 in the OWASP API Top 10 for a reason.

Flow of an API request through defense-in-depth layers: CDN/WAF, gateway, service authorization, input validation, data layer, and hardened response.

Variants

ContextApproachNotes
Internal APIsLight review, focus on auth and secretsSkip DDoS/CORS checks behind a VPN — but internal is not trusted
Partner APIsContract + reviewRequire a security questionnaire; verify HMAC request signing, timestamp, and replay protection
Public SaaS APIsFull review + penetration testThird-party pentest at least annually
GraphQLAdd depth/complexity checksLimit query nesting and computational cost
gRPCVerify mTLS certificatesValidate SANs and certificate expiry
WebSocketValidate origin, rate-limit framesPrevent frame-flooding DoS

What Works

  1. Run the review on every change that touches authentication, authorization, or input handling — not just before big releases.
  2. Automate the automatable parts: secret scanning, SAST, dependency checks, OpenAPI schema validation in CI.
  3. Require two reviewers for public-facing APIs — one from security, one from engineering.
  4. Document every exception with residual risk and a mitigation plan, or it becomes invisible debt.
  5. Rotate secrets immediately after an incident or relevant staff rotation.
  6. Get an external penetration test at least once a year for public APIs.

Common Mistakes

  1. Assuming internal APIs are safe because they sit behind a firewall — the internal network isn’t a perimeter.
  2. Validating inputs only in the frontend and trusting whatever the API client sends.
  3. Checking authentication while skipping object-level authorization — that’s BOLA, the most exploited API risk.
  4. Validating JWT signature and expiry but forgetting the audience claim.
  5. Rate limiting by IP only and ignoring authenticated consumer IDs — one user can rent a thousand IPs.
  6. Logging full request bodies, which quietly captures tokens and PII.

Troubleshooting

  • Authentication bypass in tests: test and staging users must not reach production endpoints — keep credentials and networks separate per environment.
  • Scanner false positives: tune rules against your risk profile and distinguish reachable vulnerabilities from theoretical ones before filing tickets.
  • Secrets appear in logs: redact tokens, passwords, and keys at the log sink, then audit existing sinks for leaked values.
  • Security headers break clients: roll CSP and strict headers out in report-only mode first, then enforce based on real violations.
  • Reviews go stale: assign a named security owner and a review cadence per API; a completed checklist nobody re-runs ages out within a quarter.

See Also

Frequently Asked Questions

How often should I review my APIs?

Quarterly for public APIs, twice a year for internal ones — plus on triggers: dependency upgrades, infrastructure changes, and security incidents. The continuous parts (secret scanning, SAST, dependency checks) should run in CI on every change rather than waiting for the review cycle.

Do I still need a penetration test if I use this template?

Yes. The checklist finds misconfigurations and known omissions; a pentest finds the vulnerabilities you didn't know to look for. They're complements — the checklist raises the baseline so the pentest can hunt for real flaws instead of reporting missing headers.

Should I review third-party APIs I consume?

Yes — you're trusting them with your data. Document their security posture (SOC 2, pen test reports), verify their TLS configuration, and audit exactly what data you send. Don't forward PII to a third party without a Data Processing Agreement.

What tools can automate parts of this checklist?

Several categories: SAST (Semgrep, SonarQube) for code-level issues, DAST (OWASP ZAP, Burp Suite) for runtime testing, dependency scanning (Snyk, Dependabot), secret scanning (GitLeaks, TruffleHog), and API-specific validation against your OpenAPI spec (42Crunch, StackHawk). Wire them into CI so the mechanical checks run on every PR.

How should I prioritize dependencies with known vulnerabilities?

Triage by severity and exploitability, not just CVSS score. Patch criticals (9.0+) within days, document mediums with a mitigation plan, and check CISA's KEV catalog — a CVE under active exploitation outranks a higher score nobody's exploiting. Dependency scanners (Snyk, Dependabot) surface new findings early; the API9 check in the template covers the inventory side.

Which security headers matter for an API?

HSTS (Strict-Transport-Security, one year minimum), X-Content-Type-Options: nosniff, Cache-Control: no-store on sensitive responses, and a CORS policy that names specific origins rather than *. For endpoints serving HTML add CSP with frame-ancestors (the modern replacement for X-Frame-Options). X-Request-ID isn't a defense but makes log correlation far easier during an incident.

How do we review webhook security?

Treat inbound webhooks like any other exposed endpoint. Verify the signature on every payload (HMAC or asymmetric) before processing, reject timestamps older than ~5 minutes to stop replays, and make processing idempotent so a retried webhook can't double-apply. Return 200 quickly and process asynchronously — slow receivers trigger the sender's retry storm. Log every received webhook for audit, and rate-limit the endpoint itself.

What about old API versions — are they a security risk?

Yes, that's API9 (Improper Inventory Management). Deprecated versions keep accepting traffic with known holes. Document each version's lifecycle (GA, deprecation, sunset), send Deprecation and Sunset headers, monitor usage of old versions, and accelerate sunset when usage drops low enough. Apply critical fixes to deprecated versions only as a bridge while you migrate consumers — not as a maintenance model.