--- name: api-hardening description: API security hardening patterns. Use when implementing rate limiting, input validation, CORS configuration, API key management, request throttling, or protecting endpoints from abuse. Covers defense-in-depth strategies for REST APIs with practical implementations for Express, FastAPI, and serverless, oriented around the OWASP API Security Top 10:2023. --- # API hardening Defense-in-depth patterns for protecting APIs from abuse, injection attacks, and data leakage. Recipes are oriented around the OWASP API Security Top 10:2023 and were last verified on 2026-05-08. ## Step 0: Research the current security landscape (do this first) > Security knowledge ages on a 6-12 month half-life. The recipes below were last verified on 2026-05-08; they may be stale by the time you read this. Before applying any pattern in this skill, fan out research scoped to the API surface or web defense being added so the recipes are interpreted against current authoritative sources, not against this file's snapshot. ### Default-on, with a documented skip Run the 4-angle research below by default. Skip ONLY when ALL of these hold: - (a) You ran this same skill on this same primitive within the last 4 hours of the current session, - (b) That prior research surfaced no urgent advisories for the API surface or web defense being added, - (c) You log a one-line `Research skipped because ` note in your response. "I think I know" / "moving fast" / "user wants this done quickly" / "already familiar" are NOT valid skip reasons. The whole point of this preamble is that future-you should not trust this skill body's defaults until current state is checked. ### Fan out 4 subagents in parallel Each subagent returns ≤300 words of bullets with citations. Dispatch all 4 in a single message so they run concurrently. **Angle 1 — Authoritative standards.** Have NIST / OWASP / IETF (RFCs and Internet-Drafts) / W3C / CISA published anything new about the API surface or web defense being added in the last 6-12 months? Look for: spec finalizations, deprecations, replacement specs, RFC publications, draft revisions, NIST SP updates, OWASP project version bumps. Cite by document number + publication date. **Angle 2 — Active exploitation.** What's actively being exploited that targets the API surface or web defense being added? Pull from: CISA Known Exploited Vulnerabilities (KEV) catalog (filter to last 6-12 months), recent CVE / GHSA entries with high CVSS or in-the-wild exploitation, breach postmortems and incident reports (CSRB, vendor RCAs, security-vendor research). Surface CWE patterns dominating recent KEV adds. Cite by CVE number + advisory URL. **Angle 3 — Tooling and library state.** Are the libraries this skill recommends still current? What are the latest major versions in the relevant package registry (npm / PyPI / RubyGems / crates.io)? Have any been deprecated, replaced, or merged into another project? Have any flipped a secure default? Look up current versions in: registry.npmjs.org, pypi.org, rubygems.org, crates.io, pkg.go.dev. Cite by package + version + release date. **Angle 4 — Practitioner discourse.** What are practitioners and security teams talking about in the last 6 months? Pull from: OWASP Cheat Sheet Series (last-modified date matters), GitHub Security Lab posts, vendor security blogs (Cloudflare, Fastly, Snyk, Datadog, Wiz, GitGuardian), conference talks (Black Hat, DEF CON, OWASP Global AppSec, USENIX Security), SANS ISC, Krebs, recent OWASP project re-releases. Surface the patterns being adopted and the anti-patterns being called out. Cite by post URL + author + date. ### Synthesize before applying recipes After the 4 returns land, write a 1-paragraph "current state for the API surface or web defense being added, as of " that names: - The current normative ceiling (what specs say SHOULD be the default in 2026). - 1-2 active threats specific to the API surface or web defense being added from the last 6-12 months. - Any tooling drift (deprecated lib, new default in a framework, package merged or replaced). - Any practitioner consensus shift visible in recent cheat sheet / blog updates. If the synthesis flags drift in this skill body's recipes (e.g., a spec finalized after 2026-05-08, a library now deprecated, a default flipped), call that out explicitly in your response and override the skill body where they conflict. The synthesis wins. The skill body is scaffolding, not scripture. ### When you cannot run subagents If subagents are not available in your runtime, the same shape applies in-line: do 4 sequential targeted searches (web search for standards, KEV catalog lookup, package registry version checks, recent cheat-sheet diff). Land the same 1-paragraph synthesis. Cost goes up; the protection does not change. ## OWASP API Security Top 10:2023 mapping The active edition for API-specific threat modeling is the OWASP API Security Top 10:2023 (https://owasp.org/API-Security/editions/2023/en/0x00-header/). The general OWASP Top 10:2025 (released late 2025, succeeding the 2021 edition) covers web applications more broadly; for an API surface, the 2023 API-specific list is the right framing. The 2023 categories, and which sections of this skill speak to each: - **API1:2023 Broken object level authorization** — enforce per-object access checks; covered alongside API key management and per-user rate limiting. - **API2:2023 Broken authentication** — see the `secure-auth` skill for the auth primitive itself; this skill covers rate limits, request size, and timeout protections that flank auth endpoints. - **API3:2023 Broken object property level authorization** — input validation (Zod / Pydantic) and explicit allowlist of writable fields. - **API4:2023 Unrestricted resource consumption** — rate limiting, request size limits, timeout protection, file upload limits. - **API5:2023 Broken function level authorization** — out of scope here; route-level auth lives in your framework. - **API6:2023 Unrestricted access to sensitive business flows** — graph-traversal quotas, per-account read budgets, behavioral signals for credential stuffing. - **API7:2023 Server side request forgery** — outbound URL allowlists; covered briefly under timeout protection and external API calls. - **API8:2023 Security misconfiguration** — security headers, TLS posture, CORS configuration. - **API9:2023 Improper inventory management** — out of scope here; an API gateway / catalog problem. - **API10:2023 Unsafe consumption of APIs** — input validation on data fetched from upstream, plus deserialization safety. For the broader web context, OWASP Top 10:2025 reorders the 2021 list. Notable shifts: A03:2025 "Software Supply Chain Failures" absorbs the old 2021 A06 "Vulnerable and Outdated Components" — that 2021 category is dissolved into the supply-chain category. A09:2025 is "Security Logging and Alerting Failures" (previously "Logging and Monitoring"). The 2025 ordering: A01 Broken Access Control / A02 Security Misconfiguration / A03 Software Supply Chain Failures / A04 Cryptographic Failures / A05 Injection / A06 Insecure Design / A07 Authentication Failures / A08 Software or Data Integrity Failures / A09 Security Logging and Alerting Failures / A10 Mishandling of Exceptional Conditions. ## Threat exemplars Real 2023-2024 incidents that anchor the patterns in this skill. Cite these when explaining "why" to stakeholders. - **Polyfill.io supply-chain attack (2024-06-25).** Funnull acquired the polyfill.io domain in February 2024 and injected malware into roughly 110,000 sites that loaded the script (per https://sansec.io/research/polyfill-supply-chain-attack). Lesson: every third-party ` ``` Generate an SRI hash from a fetched asset: ```bash curl -fsSL https://cdn.example.com/lib.min.js \ | openssl dgst -sha384 -binary \ | openssl base64 -A ``` cdnjs and jsdelivr include `integrity` attributes in their copy-paste snippets; unpkg has an "SRI-on" mode. Use them. Pin to a specific version, never `@latest`. ## TLS posture Maps to OWASP Top 10:2025 A04 (cryptographic failures) and API8:2023 (security misconfiguration). - **Default to TLS 1.3** — RFC 8446 (https://datatracker.ietf.org/doc/rfc8446/), published August 2018. - **Minimum TLS 1.2** — older versions are deprecated. - **Disable TLS 1.0 and TLS 1.1** — RFC 8996 / BCP 195 (https://datatracker.ietf.org/doc/rfc8996/), March 2021, formally deprecates both. - **SSL Labs caps non-TLS-1.3 servers at A-** since v2009r (16 May 2025). If you want an A or A+ grade, TLS 1.3 has to be available. - **Direction of travel: post-quantum hybrid key exchange.** Cloudflare reported that more than half of its HTTPS traffic in late 2025 negotiated post-quantum hybrid key exchange (X25519+Kyber / X25519MLKEM768). This is moving fast; check your CDN / load balancer for current support. If you operate behind a managed edge (Cloudflare, Fastly, AWS CloudFront, Azure Front Door), the right knob is usually a single "minimum TLS version" setting — set it to 1.2 at minimum, prefer 1.3, and let the edge handle the cipher suite negotiation. If you terminate TLS yourself, consult the Mozilla SSL Configuration Generator (https://ssl-config.mozilla.org/) for current "intermediate" or "modern" profiles. ## Timeout protection Maps to API4:2023 (unrestricted resource consumption) and API7:2023 (server side request forgery — pair timeouts with outbound URL allowlists). ```javascript // Request timeout middleware function timeout(ms) { return (req, res, next) => { res.setTimeout(ms, () => { res.status(408).json({ error: 'Request timeout' }); }); next(); }; } app.use(timeout(30000)); // 30 second default // External API call timeout async function fetchWithTimeout(url, options = {}, timeoutMs = 5000) { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeoutMs); try { const response = await fetch(url, { ...options, signal: controller.signal }); return response; } finally { clearTimeout(timeoutId); } } // Database query timeout const result = await db.query({ text: 'SELECT * FROM large_table WHERE condition = $1', values: [value], timeout: 5000 // 5 second query timeout }); ``` ## FastAPI (Python) equivalents Library versions current as of 2026-05-08 (verify on PyPI before pinning): - `fastapi` is on the 0.x line (0.136.1 current; pre-1.0, so pin by minor — breaking changes can land between minors). - `slowapi` is on the 0.1.x line (pre-1.0; pin by minor). - `pydantic` is on the 2.x line (2.13.4 current). ```python from fastapi import FastAPI, Depends, HTTPException, Request from fastapi.middleware.cors import CORSMiddleware from slowapi import Limiter from slowapi.util import get_remote_address from pydantic import BaseModel, EmailStr, Field import hashlib import secrets app = FastAPI() # CORS app.add_middleware( CORSMiddleware, allow_origins=["https://yourapp.com"], allow_credentials=True, allow_methods=["GET", "POST", "PUT", "DELETE"], allow_headers=["*"], ) # Rate limiting limiter = Limiter(key_func=get_remote_address) app.state.limiter = limiter @app.post("/api/login") @limiter.limit("5/minute") async def login(request: Request, credentials: LoginRequest): # Handle login pass # Input validation with Pydantic 2.x class CreateUserRequest(BaseModel): email: EmailStr password: str = Field(min_length=12, max_length=128) name: str = Field(max_length=100, default=None) @app.post("/users") async def create_user(user: CreateUserRequest): # Data is already validated pass # API key generation def generate_api_key() -> str: return f"sk_live_{secrets.token_urlsafe(24)}" def hash_api_key(key: str) -> str: return hashlib.sha256(key.encode()).hexdigest() ``` ## Security checklist for APIs Organized by OWASP API Security Top 10:2023 category. Skip categories that don't apply (API5 / API9 are out of scope here). ### API1:2023 Broken object level authorization - [ ] Per-object access checks on every fetch / update / delete - [ ] API keys scoped to a user, not shared across tenants - [ ] Object IDs aren't predictable or enumerable when that matters ### API2:2023 Broken authentication - [ ] Auth endpoints have stricter rate limits than general API endpoints - [ ] Password reset endpoints have very strict per-account limits - [ ] All auth flows over HTTPS only - [ ] See the `secure-auth` skill for the auth primitive itself ### API3:2023 Broken object property level authorization - [ ] Input validated against a schema (Zod / Pydantic) - [ ] Writable fields are explicitly allowlisted, not "everything in the body" - [ ] Mass-assignment paths (`Object.assign`, `model.update(req.body)`) avoided ### API4:2023 Unrestricted resource consumption - [ ] Rate limiting on all endpoints - [ ] Request body size limits configured - [ ] File upload size and count limits configured - [ ] Timeouts on all DB queries and external calls - [ ] Pagination caps on list endpoints ### API6:2023 Unrestricted access to sensitive business flows - [ ] Per-account quotas on graph / relationship / fan-out endpoints (23andMe lesson) - [ ] Behavioral signals (impossible-travel, device fingerprint) for credential-stuffing-prone endpoints - [ ] WAF or bot management in front for distributed abuse patterns ### API7:2023 Server side request forgery - [ ] Outbound HTTP calls go to allowlisted hosts only - [ ] Timeouts on every outbound call - [ ] Cloud metadata endpoints blocked at the network layer ### API8:2023 Security misconfiguration - [ ] Strict CSP3: nonce + `'strict-dynamic'` + Trusted Types - [ ] HSTS with `max-age=63072000; includeSubDomains; preload` - [ ] COOP / COEP / CORP set - [ ] Permissions-Policy restricting dangerous features - [ ] `X-Content-Type-Options: nosniff` - [ ] `X-XSS-Protection` NOT set (deprecated) - [ ] `X-Frame-Options` replaced by CSP `frame-ancestors` - [ ] CORS configured to specific origins, never `*` with credentials - [ ] TLS 1.3 default, TLS 1.2 minimum, TLS 1.0/1.1 disabled - [ ] SRI hashes on every third-party `