Deprecated API Versions as an Overlooked Risk

Deprecated API Versions as an Overlooked Risk

Deprecated API versions are one of the most common gaps in web application security, because an endpoint marked “deprecated” in the docs usually keeps answering requests in production for months or years. If you run a product with a public or mobile-facing API, those old versions are probably still reachable. They often lack the authorization checks, rate limits and input validation your team added later. This article covers why deprecated API versions become an attack surface, how to find the ones you forgot, and how to retire them without breaking customers.

Why Old Endpoints Outlive Their Documentation

APIs rarely die cleanly. A team ships /api/v2/ and updates the developer portal. It then leaves /api/v1/ running because a 2021 build of the iOS app still calls it, or because one enterprise customer’s integration was never migrated.

Here is how it usually plays out. A SaaS company fixes an insecure direct object reference in /v2/users/{id}/invoices by adding an ownership check in the new controller. The v1 controller sits in a separate module that nobody touched after the migration, and it still returns any invoice for any numeric ID. Eighteen months later a pentester finds the old path in a decompiled APK and pulls thousands of invoices with a simple loop. Nobody hacked v2. Nobody had to.

OWASP recognized this pattern formally. The OWASP API Security Top 10 (2023) lists it as API9:2023 Improper Inventory Management, and it names old API versions and unpatched non-production hosts as its core examples. The Optus breach in September 2022, which exposed data on roughly 9.8 million customers, was widely reported to involve an internet-facing API endpoint that did not require authentication. The broader lesson is older. Facebook’s Graph API v1.0 allowed apps to collect friends’ data, and that behaviour was only fully shut down in April 2015. Cambridge Analytica’s data set was built on that old permission model.

The Myth: “Deprecated Means Disabled”

The most persistent misconception is that deprecating a version reduces its risk. It doesn’t. Deprecation is a communication step: a line in the changelog, maybe a Deprecation or Sunset response header. The code still runs, the database connection still works, and the route still resolves.

A second version of this myth says that because both versions share a backend, security fixes apply to both automatically. Sometimes they do. More often, authorization lives in the controller or serializer layer, and each version has its own. A patched v2 serializer that drops the password_hash field doesn’t help v1 if v1 uses a different serializer. The same goes for mass assignment protections: an allowlist added to v2 does nothing for a v1 endpoint that still binds the raw request body to the model. More on that pattern in mass assignment vulnerabilities in API endpoints.

Finding Deprecated API Versions You Forgot About

An experienced API security reviewer starts with traffic, not documentation. Documentation describes what the team intended. Access logs show what is actually exposed. The practical sequence looks like this:

1. Pull 30 days of gateway or load balancer logs (AWS API Gateway, Kong, NGINX, Cloudflare) and group requests by path prefix and version segment. Any version with non-zero traffic is live.
2. Enumerate routes directly from the code. In Express, Django REST Framework or Spring, dump the registered routes and compare them to your OpenAPI spec. Routes that aren’t in the spec are shadow endpoints.
3. Probe predictable patterns such as /v1/, /v0/, /api/beta/, /internal/, and version headers like Accept: application/vnd.company.v1+json. Attackers run tools like Kiterunner against these same patterns.
4. Check old client artifacts. Decompile the oldest supported Android APK and grep for hostnames and paths. Legacy mobile builds are often the best map of forgotten endpoints.
5. Diff security controls between versions for authentication, object-level authorization, rate limiting and response fields, endpoint by endpoint.

Step five is where the findings turn up. A v1 endpoint that accepts a long-lived API key, while v2 requires OAuth 2.0 with scoped tokens, is effectively a way around your whole authentication redesign. The token-level details are covered in API authentication, OAuth scopes and token handling.

Automated vulnerability scanning helps here as a daily baseline. A scanner that tests API and GraphQL endpoints for SQL injection, XSS, SSRF and missing security headers catches regressions on routes it knows about. It will only test old routes it can reach, though, so feed it the full inventory rather than just the current spec.

Common Mistakes When Retiring Old API Versions

Announcing a sunset date and never enforcing it. Teams publish “v1 will be removed on 1 March 2025”, then extend it three times because a partner complains. By the fourth extension nobody tracks the date, and v1 is running on a runtime that stopped getting security updates. Node.js 16, for example, reached end of life in September 2023, and many legacy API services still run it.

Excluding legacy versions from monitoring. WAF rules, anomaly detection and rate limiting get configured for the current version’s path prefix only. The old version ends up with the least observation and the weakest controls, which is exactly what an attacker looks for. The API rate limiting policy should cover every live prefix, not just the documented one.

Treating zero traffic as proof of safety. An endpoint with no legitimate traffic still accepts requests. The fact that no legitimate client uses it means any request that does show up is worth investigating.

A Realistic Retirement Timeline

For a typical B2B API, a workable path takes about six months. In month one, add the Deprecation header (standardized as RFC 9745 in March 2025) and the Sunset header (RFC 8594) to every v1 response, and email the owners of API keys that still call v1. From month two to month four, bring v1 up to v2’s authorization and rate-limit controls. That feels like wasted effort on code you are about to delete, but it closes the risk window. In month five, run brownouts: return 410 Gone for one hour, then a full day, and see who shows up. In month six, remove the routes, and keep a catch-all that logs any remaining calls.

There are exceptions. Mobile apps with a long tail of unupdated installs may need a forced-upgrade screen before you can safely remove anything. Regulated sectors such as banking under PSD2 or healthcare integrations under HL7 FHIR often have contractual notice periods of 12 months or more. On-prem or single-tenant customers may run versions you can’t change at all, and in that case the risk moves into their network and should be written down in the contract. Teams under 10 people should skip the elaborate process and simply refuse to run more than two live versions at once.

FAQ: Deprecated API Versions

Should deprecated API versions get security patches?
Yes, for as long as they respond to requests. Any live endpoint needs the same authentication, authorization and input validation as the current version, whatever its lifecycle status.

Is blocking v1 at the WAF enough to retire it?
It works as an emergency measure but not as a permanent fix. WAF rules get rewritten, bypassed through alternate hostnames or disabled during troubleshooting. Remove the routes from the application itself.

How do attackers discover old API versions?
They decompile mobile apps, read archived JavaScript bundles on the Wayback Machine, search GitHub for leaked client code, and brute-force version prefixes with tools like Kiterunner and ffuf.

The Practical Takeaway

Treat every responding API version as production, because attackers do. Keep a single inventory built from real traffic and code rather than from documentation. Bring old versions up to current security controls before retiring them, and give every deprecation a sunset date you actually enforce. An old endpoint you have deleted can’t be exploited. One that is only marked deprecated can be. For broader hardening beyond versioning, the REST API security best practices guide is a good next step.