v1 API Accessible with v2 Tokens: Full CRUD Without Scope Enforcement

How v2 API tokens could access legacy v1 endpoints with zero scope checks, enabling full CRUD and bypassing role-based restrictions.

The Target

A SaaS product management platform with both a legacy v1 API and a newer v2 API. The v2 API uses OAuth scopes to restrict what a token can do. The v1 API predates this scope model.

The Discovery

I generated a v2 Personal Access Token and tried hitting the legacy v1 endpoints with it. Every single one worked. No scope enforcement at all. A token with only entities:read scope could create notes, create companies, modify features, and even delete objectives via the v1 API.

The v1 API also had weaker authorization checks. The v2 API blocks assigning a viewer-role user as a feature owner with "Only active admin or maker can be owner!" The v1 API accepted it without complaint.

What Worked

1

Read everything: Notes (36 returned), users with emails, companies with domains, features, objectives, releases, release groups, products, components, and feature statuses. All accessible via v1 with a v2 read-only token.

2

Write without scope: Created notes and companies via v1 POST endpoints. Both returned 201 Created. No notes:write or companies:write scope was required.

3

Role check bypass: Used v1 PATCH to set a viewer-role user as feature owner. The v2 API explicitly blocks this, but v1 has no role validation at all.

4

Destructive operations: Confirmed DELETE works on objectives via v1. Permanently destroyed the resource, no scope check. Also confirmed PATCH to modify objective names, changes persisted.

Impact

  • A read-only scoped token can create, modify, and delete resources via v1 endpoints
  • Weaker role checks on v1 allow actions the v2 API explicitly blocks
  • Tokens have no expiry and no API-accessible revocation endpoint
  • Confirmed across notes, companies, users, features, objectives, and releases

Timeline

Reported and triaged within two weeks. The team acknowledged the scope gap and the feature owner role bypass. Rated Medium overall. The v1 API is planned for deprecation but remains active.

Takeaway

When a platform has multiple API versions, always test whether tokens from the newer version work on the legacy endpoints. Legacy APIs often predate the scope model and have weaker authorization checks. In this case, the v2 API had proper scoping and role validation, but the v1 API was a completely unprotected backdoor that accepted the same tokens. If you find a v1 API, try everything: reads, writes, deletes, and role-restricted operations.

← Back to Blog