Vibe Security Radar
Back to Vulnerabilities

CVE-2026-30944

Mar 7, 2026CWE-639CWE-863
TypeScript
Verified by claude-opus-4-6, gemini-3-flash-preview, gemini-3.1-pro-preview, gpt-5.4
Severity
HIGH8.8
Verdict
CONFIRMED
medium confidence
AI Tool
GitHub CopilotGitHub Copilot
Confidence
63%

StudioCMS has Privilege Escalation via Insecure API Token Generation

How AI Introduced This

The fix changes only the ordering of `availablePermissionRanks`, and the repository uses `availablePermissionRanks.indexOf(...)` to compare authorization levels when creating, updating, and revoking API tokens and user roles. In the bug-introducing commit, this array was first added in descending privilege order (`['owner','admin','editor','visitor','unknown']`), which makes numeric comparisons like `targetPerms >= userPerms` backwards and allows lower-privileged users to satisfy checks intended to block higher-privilege operations. Because the vulnerable rank ordering originated in this commit and was later corrected to ascending order, this commit introduced the vulnerability.

Bug-Introducing Commits(1)

feat(@withstudiocms/auth-kit): Part-1 new package (#735)

Adam MatthiesenAug 29, 2025packages/@withstudiocms/auth-kit/src/types.tsBlame: 90%

Tribunal Analysis

3 agents
CONFIRMEDmedium
CONFIRMEDGPT-5.4
98%

The fix changes only the ordering of `availablePermissionRanks`, and the repository uses `availablePermissionRanks.indexOf(...)` to compare authorization levels when creating, updating, and revoking API tokens and user roles. In the bug-introducing commit, this array was first added in descending privilege order (`['owner','admin','editor','visitor','unknown']`), which makes numeric comparisons like `targetPerms >= userPerms` backwards and allows lower-privileged users to satisfy checks intended to block higher-privilege operations. Because the vulnerable rank ordering originated in this commit and was later corrected to ascending order, this commit introduced the vulnerability.

  • Fix commit changes `availablePermissionRanks` from `['owner','admin','editor','visitor','unknown']` to `['unknown','visitor','editor','admin','owner']` in `packages/@withstudiocms/auth-kit/src/types.ts`.
  • At the fixed revision, `packages/studiocms/frontend/pages/studiocms_api/_handlers/dashboard/apiTokens.ts` compares permissions via `const targetPerms = availablePermissionRanks.indexOf(tokenData.rank); const userPerms = availablePermissionRanks.indexOf(userData.permissionLevel); if (targetPerms >= userPerms) ...`, so array order defines authorization semantics.
  • The suspected BIC `341b59e3c775f619e9630c9044772ef0f16d1970` is the commit that introduced `packages/@withstudiocms/auth-kit/src/types.ts` with the incorrect descending order of `availablePermissionRanks`.
CONFIRMEDClaude Opus 4.6
92%

The BIC (341b59e3) created the `availablePermissionRanks` array in `packages/@withstudiocms/auth-kit/src/types.ts` with the order `['owner', 'admin', 'editor', 'visitor', 'unknown']`, placing the highest privilege ('owner') at index 0 and the lowest ('unknown') at index 4. Later code used `availablePermissionRanks.indexOf()` for permission comparisons assuming higher index = higher privilege, which inverted the permission hierarchy. This allowed lower-privileged users (e.g., 'unknown' at index 4) to pass permission checks that should have required higher privileges (e.g., 'owner' at index 0), enabling privilege escalation. The fix correctly reverses the array to `['unknown', 'visitor', 'editor', 'admin', 'owner']`. The BIC is the root cause because it introduced the incorrectly-ordered constant that was exported and consumed by permission-checking code.

  • The BIC introduced `availablePermissionRanks = ['owner', 'admin', 'editor', 'visitor', 'unknown']` with owner at index 0 and unknown at index 4
  • The fix reverses the order to `['unknown', 'visitor', 'editor', 'admin', 'owner']` so higher index = higher privilege
  • Permission checks use `availablePermissionRanks.indexOf()` with comparisons like `if (targetPerm >= callerPerm)` and `if (userPerms <= targetCurrentLevel)`, which assume higher index means higher privilege
  • With the old order, an 'unknown' user (index 4) would appear to have higher permissions than an 'owner' (index 0), enabling privilege escalation
  • The array was exported from auth-kit and consumed by multiple API handlers for authorization decisions
UNLIKELYGemini 3.1 Pro
30%

Fallback verdict: Agent exhausted max turns without submitting a verdict.

Causality Analysisby Gemini 3 Flash
VulnerabilityBroken Access Control / IDOR
Root CauseThe API endpoint accepts a tokenID and userID to delete an API token without verifying if the requesting user owns the token or has sufficient administrative privileges to delete other users' tokens.
Pattern
yield* sdk.REST_API.tokens.delete({ tokenId: tokenID, userId: userID }); // without checking if the current user matches userID or has admin rights
AI Signals(1)
Commit341b59e
GitHub CopilotCo-author trailer (generic)Co-authored-by: Copilot70%
Fix Commits(2)
References(6)