API Security · 2026
Securing REST APIs: A 2026 Engineering Guide
REST's stateless, resource-oriented design is simple to build and easy to get subtly wrong. This is the practitioner's guide to the REST-specific controls that matter: transport, authentication, CORS, HTTP method and status discipline, error handling, and versioning — with code and MITRE ATT&CK mapping.

Quick answer
Secure a REST API by enforcing TLS everywhere, authenticating every request and authorizing every resource on the server, restricting CORS to an explicit origin allow-list, mapping each route to the correct HTTP method, returning minimal error bodies with the right status code, and rate-limiting every endpoint. Get the REST-specific details right — they are where these APIs most often leak. Then verify with authenticated, role-aware penetration testing.
This guide focuses on the controls specific to REST — the HTTP-level details, CORS, and error discipline that the protocol's design makes easy to fumble. For the full risk taxonomy and the authorization-first ordering of the OWASP API Top 10, pair it with our API security best practices guide. We build APIs for a living — our API development practice bakes these defenses in, and our web app pentest tests them.
1. Transport and authentication
Every REST endpoint must be served over TLS — including internal service-to-service calls — so credentials and data are never exposed on the wire. On top of that, authenticate every request using a standard: short-lived bearer tokens for user and service calls, scoped API keys only where a full token flow is impractical. Validate the token on every request; never trust one because it "looks right."
- Enforce TLS and HSTS; redirect plain HTTP and reject downgrade. See what TLS is for the primer.
- Validate token signature, issuer, audience, and expiry on every request. Keep access tokens short-lived.
- Send credentials in the
Authorizationheader, not the URL — query strings end up in logs and proxies.
ATT&CK link: weak authentication enables Valid Accounts (T1078); cleartext transport enables Adversary-in-the-Middle (T1557).
2. CORS: a browser control, not an access control
Cross-Origin Resource Sharing decides which web origins a browser will let read your responses. It is routinely misconfigured into a vulnerability by reflecting the request's Origin back unconditionally — which effectively allows every site — especially when combined with credentials.
// VULNERABLE — reflects any origin AND allows credentials
res.setHeader("Access-Control-Allow-Origin", req.headers.origin);
res.setHeader("Access-Control-Allow-Credentials", "true");
// FIXED — allow-list the origin; only then send credentials
const ALLOWED = new Set(["https://app.example.com"]);
const origin = req.headers.origin;
if (origin && ALLOWED.has(origin)) {
res.setHeader("Access-Control-Allow-Origin", origin);
res.setHeader("Vary", "Origin");
res.setHeader("Access-Control-Allow-Credentials", "true");
}- Never combine
Allow-Origin: *with credentials — and never reflect an unvalidated origin. - Restrict allowed methods and headers to what the API actually uses.
- Remember CORS does not authenticate or authorize — server-side checks still do all the real work.
3. HTTP method and status discipline
REST leans on HTTP semantics, and those semantics carry security guarantees. GET and HEAD must be safe — no state change — because browsers, caches, and crawlers may call them at will. A mutation behind a GET can be triggered by a prefetch or a cached link and sidesteps CSRF assumptions entirely.
- Map each route to the correct verb; reject method mismatches with
405rather than handling them anyway. - For cookie-based sessions, require CSRF protection on mutating verbs; token-in-header auth is naturally resistant.
- Use status codes deliberately —
401for unauthenticated,403for forbidden,429for rate-limited.
ATT&CK link: method and request abuse maps to Exploit Public-Facing Application (T1190).
4. Error handling and information disclosure
A verbose error response is a free reconnaissance gift. Stack traces, SQL fragments, file paths, and framework version banners tell an attacker exactly what you are running and where the seams are. Return a minimal, structured body and log the detail server-side.
// VULNERABLE — leaks internals to the client
catch (err) {
res.status(500).json({ error: err.stack }); // SQL, paths, versions
}
// FIXED — log detail server-side, return an opaque body
catch (err) {
logger.error({ err, reqId: req.id });
res.status(500).json({ error: "internal_error", reqId: req.id });
}- Strip server banners and
X-Powered-By; do not advertise your stack. - Return
404instead of403where existence itself is sensitive. - Validate every input against a strict schema at the boundary — parameterize all database access (see preventing SQL injection).
5. Versioning, inventory, and rate limiting
Forgotten endpoints are how breaches happen. An old /v1 still live after /v2 shipped, an undocumented staging route, or a debug endpoint left enabled — each is an unmonitored door. Pair a clean versioning strategy with an authoritative inventory and rate limits on everything.
- Maintain an up-to-date inventory of every endpoint and version; decommission deliberately, do not just stop documenting.
- Rate-limit per authenticated identity and per IP, with tighter limits on expensive routes; return
429withRetry-After. - Log authentication, authorization-denied, and high-value actions, and alert on anomalies.
ATT&CK link: forgotten endpoints feed Exploit Public-Facing Application (T1190); missing limits enable Endpoint Denial of Service (T1499).
Mid-post: test the API, don't just harden it
Hardening is half the work. An authenticated, role-aware API pentest proves your CORS, auth, and authorization checks actually hold. Book a free scoping call.
REST security checklist at a glance
| Control | What good looks like |
|---|---|
| Transport | TLS + HSTS everywhere; no plaintext, no downgrade |
| Auth | Short-lived tokens validated on every request |
| CORS | Explicit origin allow-list; no wildcard with credentials |
| Methods | Safe verbs are side-effect-free; mismatches return 405 |
| Errors | Minimal bodies; detail logged server-side, not returned |
| Inventory | Every endpoint and version tracked; old routes retired |
For the authorization-first risk ordering, see API security best practices and the glossary entry on APIs.
Operational practices that hold over time
REST APIs sprawl as products grow. Three habits keep them secure past launch day:
- Contract-driven testing. Lint your OpenAPI spec and reject requests that do not match it — a strong contract is also a security boundary.
- Secrets hygiene. Keep keys in a secrets manager and out of client bundles — the pattern is in secrets management best practices.
- Regular testing. Re-test after any release that changes auth or data access. For SaaS teams, the broader view is in cybersecurity services for SaaS startups.
Frequently asked questions
What does it mean to secure a REST API?
It means enforcing transport security, authentication, and authorization on every endpoint, while also getting the REST-specific details right: correct HTTP method semantics, conservative CORS, safe error handling that does not leak internals, strict input validation, and rate limiting. REST's stateless, resource-oriented design has its own pitfalls — verbs that mutate on a GET, overly permissive cross-origin headers, and verbose stack traces in error bodies are common, exploitable mistakes that are unique to how REST APIs are built.
How should a REST API handle CORS securely?
Reflect only an explicit allow-list of trusted origins, never echo the request's Origin header blindly, and never combine a wildcard origin with credentials — browsers forbid it for good reason. Restrict allowed methods and headers to what the API actually uses, keep preflight cache durations reasonable, and remember that CORS is a browser protection, not server-side access control. CORS decides which web origins may read responses; it does not authenticate or authorize the request itself.
Why do HTTP methods matter for REST API security?
Because method semantics encode safety guarantees that caches, proxies, and crawlers rely on. GET and HEAD must be safe and side-effect-free; a GET that mutates state can be triggered by a prefetch or a cached link and bypasses CSRF assumptions. Mutating verbs (POST, PUT, PATCH, DELETE) should require authentication and, for cookie-based sessions, CSRF protection. Map each route to the correct method and reject mismatches rather than treating all verbs the same.
How should a REST API return errors safely?
Return the correct status code with a minimal, structured body — and nothing more. A 500 should not include a stack trace, SQL fragment, file path, or framework version, all of which hand an attacker a map of your internals. Use 401 versus 403 deliberately, return 404 instead of 403 where revealing that a resource exists would itself leak information, and log the full detail server-side while sending the client only what it needs to act.
Should REST APIs use API keys or tokens?
Prefer short-lived bearer tokens (OAuth 2.0 / OpenID Connect access tokens) for user-facing and service-to-service calls, validating signature, issuer, audience, and expiry on every request. API keys are acceptable for server-to-server integrations where a full token flow is impractical, but they should be scoped to least privilege, rotated on a schedule, and never embedded in client-side or mobile bundles where they are trivially extracted.
How do you test a REST API for security issues?
With authenticated, role-aware penetration testing rather than scanning alone. A tester uses low-privilege accounts to attempt access to other users' and tenants' resources, manipulate object properties, abuse method semantics, probe CORS and error handling, and exhaust resources. Findings are mapped to the OWASP API Security Top 10 and the relevant MITRE ATT&CK techniques so engineers and auditors can prioritize and verify each fix.
Sources & references
- [1]OWASP REST Security Cheat Sheet · OWASP
- [2]OWASP API Security Top 10 (2023) · OWASP
- [3]RFC 9110 — HTTP Semantics · IETF
- [4]MITRE ATT&CK Enterprise Matrix · MITRE
Related reading and next steps
- API Development service
- Web Application Pentest service
- Penetration Testing service overview
- API security best practices (2026)
- Preventing SQL injection (2026)
- XSS prevention guide (2026)
- Secrets management best practices (2026)
- What is an API?
- The OWASP Top 10 explained (2026)
- Talk to Bill about your API security
Harden it, then prove it holds.
An authenticated API pentest maps every finding to the OWASP API Top 10 and the ATT&CK technique it enables. Book a free scoping call and we'll cover the right depth for your API.
More engineering security reading
All postsAPI Security Best Practices (2026)
Auth, rate limiting, input validation, secrets, and the OWASP API Top 10.
Read postPreventing SQL Injection in Modern Web Apps (2026)
Parameterized queries, ORMs, least-privilege DB roles, and why concatenation still breaches apps.
Read postWhat Is Penetration Testing? A Founder's Buyer Guide
What a pentest actually is, the five types you can buy, and what a real report looks like.
Read post