Skip to main content

Free 30-min security demo  — We'll scan your real code and show live findings, no commitment Book Now

Offensive360
Academy Insecure API Versioning
Intermediate · 15 min

Insecure API Versioning

Learn how deprecated API versions left accessible expose old vulnerabilities that bypass current security controls.

1 Old Vulnerable API Versions Left Exposed

When APIs are versioned, old versions are often deprecated but not removed. Attackers probe for these old versions which may lack current security controls.

Typical scenario:

GET /api/v2/users/me  → Current version with full auth + MFA check
GET /api/v1/users/me  → Old version — still works! Missing new auth requirements
GET /api/admin/users  → Unversioned legacy route — no auth at all!

Common patterns that expose old versions:

  • Deprecated /v1 routes left in the router as "backward compatibility"
  • Mobile app support keeping old versions alive for older app versions
  • Microservice APIs with versioned namespaces that lost auth middleware
  • URL rewriting rules that normalize /v1/ and /v2/ to the same backend

Real impact: Uber's 2016 breach was partly facilitated by an old API endpoint that lacked rate limiting present in the current version. Attackers enumerated the older, less-protected API.

2 Retire Old Versions and Version-Level Auth

Old API versions must be explicitly retired, and authentication must be applied at the version router level to prevent gaps.

Explicit retirement with proper redirects:

// v1 is retired — return 410 Gone with migration info
app.use("/api/v1", (req, res) => {
  res.status(410).json({
    error: "API v1 is deprecated and has been removed.",
    migration: "https://docs.myapp.com/api/migration-guide",
    currentVersion: "/api/v2"
  });
});

// v2 — current version with auth applied at version level
const v2Router = express.Router();
v2Router.use(authenticate);  // ALL v2 routes require auth
v2Router.get("/users/me", getCurrentUser);
v2Router.get("/users/:id", getUser);
app.use("/api/v2", v2Router);

Defense checklist:

  • Maintain an explicit list of all active API versions
  • Apply authentication middleware at the version router level, not per-route
  • Return 410 Gone for deprecated versions with migration documentation
  • Monitor traffic to old version routes to detect probing
  • Include sunset headers in old version responses before removal

Knowledge Check

0/3 correct
Q1

Why are old API versions a security risk even after a new version is deployed?

Q2

What HTTP status code correctly signals that an API version has been permanently removed?

Q3

Where should authentication middleware be applied to ensure no routes in an API version are missed?

Code Exercise

Retire API v1

The app still has /api/v1 routes that lack the authentication required in /api/v2. Add a catch-all handler to return 410 Gone for all v1 requests.

javascript