On October 2, 2023, T-Mobile disclosed that an attacker had pulled data on 37 million customer accounts through a single misconfigured API endpoint — no malware, no phishing, just an authenticated call that should have been scoped tighter. Nine months earlier, Optus lost records for 9.8 million Australian customers to an internet-facing API that required no authentication at all. These weren't exotic zero-days. They were the same handful of API mistakes — broken object-level authorization, missing rate limits, over-permissioned tokens — that show up on the OWASP API Security Top 10 year after year. Securing a REST API isn't a single control; it's a set of decisions made at the schema, gateway, and code level, repeated consistently across every endpoint you ship. This post walks through the concrete controls that stop the attacks actually happening in production today.
What are the most common ways REST APIs get breached?
The most common cause is Broken Object Level Authorization (BOLA), which OWASP ranked API1:2023 — the top spot on its 2023 API Security Top 10 — and which Salt Security's State of API Security report attributes to roughly 40% of the API attacks its customers saw in 2023. BOLA happens when an endpoint like GET /invoices/{id} checks that a caller is authenticated but never checks that the caller owns invoice {id}, so incrementing the ID leaks someone else's data. This is exactly the bug class behind the 2021 Peloton API flaw that exposed private account data for any user ID an attacker guessed, and the 2019 First American Financial breach that exposed 885 million mortgage documents through sequential document IDs with no access check. The fix is boring but non-negotiable: every handler that takes a resource ID must re-verify ownership or role against the authenticated principal on that specific request, not just at login. Automated authorization tests that iterate over object IDs with a second user's token catch this class before it ships.
How should you authenticate and authorize REST API requests?
You should authenticate with short-lived, signed tokens validated on every request, and authorize with explicit, resource-level checks rather than implicit trust in the caller. In practice that means OAuth 2.1 or OpenID Connect for user-delegated access, JWTs with a lifetime of 5–15 minutes signed with RS256 or ES256 (never alg: none, which was the root cause of multiple 2015–2022 JWT bypass CVEs including CVE-2022-21449 in Java's ECDSA verification), and mTLS or signed API keys for service-to-service calls. Scope tokens narrowly — a mobile client reading its own profile does not need a token that can also call /admin/users. Coinbase's 2021 API incident, where attackers exploited a logic flaw to execute unauthorized trades, traced back to insufficiently granular permission checks on an internal API rather than a stolen credential. Rotate signing keys on a fixed schedule (30–90 days is typical), and reject any token whose iss and aud claims don't match the exact service receiving it.
How do you prevent injection and input-validation attacks on a REST API?
You prevent them by validating and rejecting malformed input at the edge, before it reaches business logic, using an explicit schema rather than a denylist. Define your API contract in OpenAPI 3.1 and validate every incoming request against it — reject unexpected fields, enforce type and length limits (e.g., cap a "notes" field at 2,000 characters instead of accepting arbitrary text), and use parameterized queries or an ORM for anything that touches a database. SQL injection remains active against production APIs: CVE-2023-34362, the MOVEit Transfer SQL injection flaw exploited by the Cl0p ransomware group starting May 2023, compromised data at more than 2,600 organizations by routing malicious input through a web API endpoint. For JSON payloads, disable unsafe deserialization features (Jackson's enableDefaultTyping, .NET's BinaryFormatter) that let an attacker instantiate arbitrary classes — this class of bug produced CVE-2017-9805 in Apache Struts, which cost Equifax a breach of 147 million records in 2017.
What rate limiting and abuse-prevention controls does a REST API need?
A REST API needs per-identity rate limits, not just per-IP limits, because API abuse increasingly comes from distributed credential-stuffing rather than a single noisy IP. API4:2023, "Unrestricted Resource Consumption," is on OWASP's current Top 10 specifically because unlimited pagination, unlimited file upload sizes, and unthrottled expensive endpoints (bulk export, search, PDF generation) let a single authenticated user exhaust backend capacity or run up cloud costs. Set limits at multiple layers: a gateway-level cap (e.g., 100 requests/minute per API key), a per-endpoint cap for expensive operations (e.g., 5 requests/minute for a report-generation endpoint), and a maximum response page size (cap limit parameters server-side even if the client requests 100,000 rows). Return HTTP 429 with a Retry-After header rather than silently dropping requests, and log rate-limit violations to your SIEM — a spike in 429s from one account is often the earliest signal of credential stuffing or scraping, arriving well before any data actually leaves.
How do you keep API secrets and dependencies from becoming the breach vector?
You keep them safe by never letting long-lived secrets sit in code or config repos and by tracking every open-source package your API runtime depends on, because a growing share of API compromises start upstream of your own code. GitGuardian's 2023 State of Secrets Sprawl report found over 12.8 million secrets leaked on public GitHub commits in 2023 alone, a 28% increase over 2022, and API keys with cloud or database access were among the most common types found. Store secrets in a dedicated manager (Vault, AWS Secrets Manager) with 90-day rotation, scan every pull request for committed credentials, and enforce least-privilege IAM roles so a leaked key can't reach more than the one service it was issued for. On the dependency side, the same REST framework and JSON/XML parsing libraries that handle your API's requests are frequent CVE targets — CVE-2022-42889 ("Text4Shell") and CVE-2021-44228 (Log4Shell) both reached production APIs through transitive dependencies most teams didn't know they had. An accurate, current software bill of materials is the only way to know which of your running services are actually exposed when the next one lands.
How Safeguard Helps
Safeguard closes the gap between knowing a CVE exists and knowing whether it matters for your specific API. Our reachability analysis traces whether a vulnerable function in a dependency — say, an XML parser flagged for a new deserialization CVE — is actually called from a path reachable by an external request, cutting through the noise of thousands of "critical" CVSS scores that never execute in your service. Griffin AI reviews API code changes and flags the exact authorization and input-validation gaps described above (missing ownership checks, unbounded page sizes, weak JWT validation) directly in the pull request, before merge. Safeguard generates and ingests SBOMs automatically on every build so you always have a live inventory of what's running behind each endpoint, and for confirmed, reachable issues it opens auto-fix PRs with the patched dependency version or the minimal code change already applied — so the fix ships in the same review cycle the vulnerability was found, not a quarter later.