API Security Checklist — Web App API Security Checklist
An OWASP-based security checklist, authentication patterns, and defense code guide that the backend-dev agent uses during API development.
Target Agent
backend-dev — Applies this skill's security checklist directly to API implementation.
OWASP API Security Top 10 Check
| Rank |
Vulnerability |
Check Item |
Defense |
| A1 |
BOLA (Broken Object Level Authorization) |
Can another user's resources be accessed? |
Verify object ownership at every endpoint |
| A2 |
Broken Authentication |
Weak passwords, unlimited login attempts? |
bcrypt hashing, Rate Limit, MFA |
| A3 |
Broken Object Property Level Authorization |
Are fields that should be hidden exposed? |
Filter fields via response DTOs |
| A4 |
Unrestricted Resource Consumption |
Can mass requests crash the server? |
Rate Limiting, enforce pagination |
| A5 |
Broken Function Level Authorization |
Can regular users call admin APIs? |
RBAC middleware |
| A6 |
Server-Side Request Forgery (SSRF) |
Can external URL input access internal resources? |
URL whitelist, block internal IPs |
| A7 |
Security Misconfiguration |
Debug mode exposed, default accounts? |
Separate production config, inspect headers |
| A8 |
Lack of Protection from Automated Threats |
Can normal APIs be called in abnormal sequences? |
State machine validation, server-side business rules |
| A9 |
Improper Asset Management |
Unused APIs, old versions exposed? |
API inventory, version deprecation policy |
| A10 |
Unsafe Consumption of APIs |
Are external API responses blindly trusted? |
Validate external responses, set timeouts |
Authentication Patterns
JWT-Based Authentication
| Item |
Recommended Setting |
| Access Token Expiry |
15-30 minutes |
| Refresh Token Expiry |
7-14 days |
| Algorithm |
RS256 (asymmetric) or HS256 (symmetric) |
| Storage |
httpOnly + secure + sameSite cookie |
| Payload |
Minimal info only (userId, role) — no PII |
| Renewal Strategy |
Silent Refresh or Rotation |
Password Policy
- Minimum 8 characters, recommend uppercase + lowercase + numbers + special chars (show strength rather than enforce)
- bcrypt (cost factor 12+) or Argon2id
- Password history (prevent reuse of last 5)
- Temporary lock after 5 failed login attempts (15 min) or CAPTCHA
Authorization Patterns
RBAC (Role-Based)
Role definitions: admin, manager, user, viewer
Permission mapping:
admin → *.* (full access)
manager → resource.create, resource.read, resource.update
user → resource.create (own), resource.read (own)
viewer → resource.read (public)
Middleware Chain
Request → [Rate Limit] → [Auth: JWT verification] → [Authorization: role check] → [Input Validation] → Handler
Input Validation Checklist
| Validation Item |
Method |
Tool |
| Type Validation |
Schema validation |
Zod, Joi, class-validator |
| Length Limits |
Min/max length |
Schema min/max |
| Pattern Matching |
Email, URL, phone |
Regex + libraries |
| Range Validation |
Number range, date range |
min/max values |
| Enumeration |
Allowed value list |
enum type |
| SQL Injection |
Parameterized queries |
ORM (Prisma, TypeORM) |
| XSS |
HTML escaping |
DOMPurify (client), server escape |
| Path Traversal |
Path normalization |
path.resolve + whitelist |
| File Upload |
Type/size validation |
MIME type + magic number verification |
HTTP Security Headers
| Header |
Value |
Purpose |
Strict-Transport-Security |
max-age=31536000; includeSubDomains |
Force HTTPS |
X-Content-Type-Options |
nosniff |
Prevent MIME sniffing |
X-Frame-Options |
DENY or SAMEORIGIN |
Prevent clickjacking |
Content-Security-Policy |
default-src 'self' |
Prevent XSS |
X-XSS-Protection |
0 (replaced by CSP) |
Legacy |
Referrer-Policy |
strict-origin-when-cross-origin |
Limit referrer info |
Permissions-Policy |
camera=(), microphone=() |
Restrict browser features |
CORS Configuration Guide
| Environment |
Setting |
| Development |
origin: 'http://localhost:3000' |
| Production |
origin: ['https://example.com'] — specify domains |
| Forbidden |
origin: '*' + credentials: true — security risk |
Required settings:
methods: Allow only necessary methods
allowedHeaders: Only necessary headers
credentials: Set to true only when cookies are needed
maxAge: Preflight caching (86400 seconds)
Rate Limiting Strategy
| Target |
Limit |
Implementation |
| Auth endpoints |
5 req/min/IP |
IP-based |
| General API |
100 req/min/user |
Token-based |
| File upload |
10 req/hour/user |
Token-based |
| Unauthenticated API |
30 req/min/IP |
IP-based |
Response Headers
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1609459200
Retry-After: 60 (on 429 response)
Error Response Security
Production Error Response Rules
- Never expose internal implementation details (stack traces, SQL queries)
- Use consistent error format
- Prevent enumeration attacks: On login failure, show "Email or password is incorrect" (don't reveal which one is wrong)
Error Response Format
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Input is invalid",
"details": [
{"field": "email", "message": "Please enter a valid email"}
]
}
}
Sensitive Data Handling
| Data Type |
Storage |
Transmission |
Logging |
| Passwords |
bcrypt hash only |
HTTPS only |
Never |
| API Keys |
Environment variables |
Header (Authorization) |
Masked (first 4 chars only) |
| PII |
Encrypted (AES-256) |
HTTPS only |
Masked |
| Credit Cards |
Tokenized (delegate to payment provider) |
Payment provider SDK |
Never |
| Sessions/Tokens |
httpOnly cookie |
HTTPS only |
Never |
1---2name: api-security-checklist3description: Web app API security checklist. Provides OWASP Top 10-based vulnerability checks, authentication/authorization patterns, input validation, Rate Limiting, CORS, CSRF, and SQL Injection defense as a backend-dev extension skill. Use for requests like 'API security', 'OWASP', 'auth implementation', 'SQL Injection', 'XSS defense', 'CORS configuration', 'security checklist', and other backend security design tasks. However, penetration testing or WAF configuration is outside this skill's scope.4---56# API Security Checklist — Web App API Security Checklist78An OWASP-based security checklist, authentication patterns, and defense code guide that the backend-dev agent uses during API development.910## Target Agent1112`backend-dev` — Applies this skill's security checklist directly to API implementation.1314## OWASP API Security Top 10 Check1516| Rank | Vulnerability | Check Item | Defense |17|------|-------------|-----------|---------|18| A1 | **BOLA** (Broken Object Level Authorization) | Can another user's resources be accessed? | Verify object ownership at every endpoint |19| A2 | **Broken Authentication** | Weak passwords, unlimited login attempts? | bcrypt hashing, Rate Limit, MFA |20| A3 | **Broken Object Property Level Authorization** | Are fields that should be hidden exposed? | Filter fields via response DTOs |21| A4 | **Unrestricted Resource Consumption** | Can mass requests crash the server? | Rate Limiting, enforce pagination |22| A5 | **Broken Function Level Authorization** | Can regular users call admin APIs? | RBAC middleware |23| A6 | **Server-Side Request Forgery (SSRF)** | Can external URL input access internal resources? | URL whitelist, block internal IPs |24| A7 | **Security Misconfiguration** | Debug mode exposed, default accounts? | Separate production config, inspect headers |25| A8 | **Lack of Protection from Automated Threats** | Can normal APIs be called in abnormal sequences? | State machine validation, server-side business rules |26| A9 | **Improper Asset Management** | Unused APIs, old versions exposed? | API inventory, version deprecation policy |27| A10 | **Unsafe Consumption of APIs** | Are external API responses blindly trusted? | Validate external responses, set timeouts |2829## Authentication Patterns3031### JWT-Based Authentication3233| Item | Recommended Setting |34|------|-------------------|35| Access Token Expiry | 15-30 minutes |36| Refresh Token Expiry | 7-14 days |37| Algorithm | RS256 (asymmetric) or HS256 (symmetric) |38| Storage | httpOnly + secure + sameSite cookie |39| Payload | Minimal info only (userId, role) — no PII |40| Renewal Strategy | Silent Refresh or Rotation |4142### Password Policy43- Minimum 8 characters, recommend uppercase + lowercase + numbers + special chars (show strength rather than enforce)44- bcrypt (cost factor 12+) or Argon2id45- Password history (prevent reuse of last 5)46- Temporary lock after 5 failed login attempts (15 min) or CAPTCHA4748## Authorization Patterns4950### RBAC (Role-Based)51```52Role definitions: admin, manager, user, viewer53Permission mapping:54 admin → *.* (full access)55 manager → resource.create, resource.read, resource.update56 user → resource.create (own), resource.read (own)57 viewer → resource.read (public)58```5960### Middleware Chain61```62Request → [Rate Limit] → [Auth: JWT verification] → [Authorization: role check] → [Input Validation] → Handler63```6465## Input Validation Checklist6667| Validation Item | Method | Tool |68|----------------|--------|------|69| **Type Validation** | Schema validation | Zod, Joi, class-validator |70| **Length Limits** | Min/max length | Schema min/max |71| **Pattern Matching** | Email, URL, phone | Regex + libraries |72| **Range Validation** | Number range, date range | min/max values |73| **Enumeration** | Allowed value list | enum type |74| **SQL Injection** | Parameterized queries | ORM (Prisma, TypeORM) |75| **XSS** | HTML escaping | DOMPurify (client), server escape |76| **Path Traversal** | Path normalization | path.resolve + whitelist |77| **File Upload** | Type/size validation | MIME type + magic number verification |7879## HTTP Security Headers8081| Header | Value | Purpose |82|--------|-------|---------|83| `Strict-Transport-Security` | `max-age=31536000; includeSubDomains` | Force HTTPS |84| `X-Content-Type-Options` | `nosniff` | Prevent MIME sniffing |85| `X-Frame-Options` | `DENY` or `SAMEORIGIN` | Prevent clickjacking |86| `Content-Security-Policy` | `default-src 'self'` | Prevent XSS |87| `X-XSS-Protection` | `0` (replaced by CSP) | Legacy |88| `Referrer-Policy` | `strict-origin-when-cross-origin` | Limit referrer info |89| `Permissions-Policy` | `camera=(), microphone=()` | Restrict browser features |9091## CORS Configuration Guide9293| Environment | Setting |94|------------|---------|95| Development | `origin: 'http://localhost:3000'` |96| Production | `origin: ['https://example.com']` — specify domains |97| Forbidden | `origin: '*'` + `credentials: true` — security risk |9899Required settings:100- `methods`: Allow only necessary methods101- `allowedHeaders`: Only necessary headers102- `credentials`: Set to true only when cookies are needed103- `maxAge`: Preflight caching (86400 seconds)104105## Rate Limiting Strategy106107| Target | Limit | Implementation |108|--------|-------|---------------|109| Auth endpoints | 5 req/min/IP | IP-based |110| General API | 100 req/min/user | Token-based |111| File upload | 10 req/hour/user | Token-based |112| Unauthenticated API | 30 req/min/IP | IP-based |113114### Response Headers115```116X-RateLimit-Limit: 100117X-RateLimit-Remaining: 95118X-RateLimit-Reset: 1609459200119Retry-After: 60 (on 429 response)120```121122## Error Response Security123124### Production Error Response Rules125- Never expose internal implementation details (stack traces, SQL queries)126- Use consistent error format127- Prevent enumeration attacks: On login failure, show "Email or password is incorrect" (don't reveal which one is wrong)128129### Error Response Format130```json131{132 "error": {133 "code": "VALIDATION_ERROR",134 "message": "Input is invalid",135 "details": [136 {"field": "email", "message": "Please enter a valid email"}137 ]138 }139}140```141142## Sensitive Data Handling143144| Data Type | Storage | Transmission | Logging |145|----------|---------|-------------|---------|146| Passwords | bcrypt hash only | HTTPS only | Never |147| API Keys | Environment variables | Header (Authorization) | Masked (first 4 chars only) |148| PII | Encrypted (AES-256) | HTTPS only | Masked |149| Credit Cards | Tokenized (delegate to payment provider) | Payment provider SDK | Never |150| Sessions/Tokens | httpOnly cookie | HTTPS only | Never |