GitHub Security Advisory: GHSA-8rgj-vrfr-6hqr
Package: studiocms (NPM)
Severity: HIGH (CVSS 7.1)
CWE: CWE-639: Authorization Bypass Through User-Controlled Key
Vulnerable versions: <= 0.3.0
Patched in: 0.4.0

Summary: StudioCMS: IDOR — Arbitrary API Token Revocation Leading to Denial of Service

Details:
## Summary
The DELETE /studiocms_api/dashboard/api-tokens endpoint allows any authenticated user with editor privileges or above to revoke API tokens belonging to any other user, including admin and owner accounts. The handler accepts tokenID and userID directly from the request payload without verifying token ownership, caller identity, or role hierarchy. This enables targeted denial of service against critical integrations and automations.

## Details
#### Vulnerable Code
The following is the server-side handler for the `DELETE /studiocms_api/dashboard/api-tokens` endpoint (`revokeApiToken`):

**File:** packages/studiocms/frontend/pages/studiocms_api/dashboard/api-tokens.ts (lines 58–99)
**Version:** studiocms@0.3.0
```
DELETE: (ctx) =>
    genLogger('studiocms/routes/api/dashboard/api-tokens.DELETE')(function* () {
        const sdk = yield* SDKCore;

        // Check if demo mode is enabled
        if (developerConfig.demoMode !== false) {
            return apiResponseLogger(403, 'Demo mode is enabled, this action is not allowed.');
        }

        // Get user data
        const userData = ctx.locals.StudioCMS.security?.userSessionData;       // [1]

        // Check if user is logged in
        if (!userData?.isLoggedIn) {                                            // [2]
            return apiResponseLogger(403, 'Unauthorized');
        }

        // Check if user has permission
        const isAuthorized = ctx.locals.StudioCMS.security?.userPermissionLevel.isEditor;  // [3]
        if (!isAuthorized) {
            return apiResponseLogger(403, 'Unauthorized');
        }

        // Get Json Data
        const jsonData = yield* readAPIContextJson<{
            tokenID: string;                                                    // [4]
            userID: string;                                                     // [5]
        }>(ctx);

        // Validate form data
        if (!jsonData.tokenID) {
            return apiResponseLogger(400, 'Invalid form data, tokenID is required');
        }

        if (!jsonData.userID) {
            return apiResponseLogger(400, 'Invalid form data, userID is required');
        }

        // [6] Both user-controlled values passed directly — no ownership or identity checks
        yield* sdk.REST_API.tokens.delete({ tokenId: jsonData.tokenID, userId: jsonData.userID });

        return apiResponseLogger(200, 'Token deleted');                         // [7]
    }),
```
**Analysis**
The handler shares the same class of authorization flaws found in the token generation endpoint, applied to a destructive operation:
1. **Insufficient permission gate [1][2][3]:** The handler retrieves the session from ctx.locals.StudioCMS.security and only checks isEditor. Token revocation is a high-privilege operation that should require ownership of the token or elevated administrative privileges — not a generic editor-level gate.
2. **No token ownership validation [4][6]:** The handler does not verify that jsonData.token