bitwarden/server
Vault & ciphers
Active contributors: vault team.
Purpose
The vault is what Bitwarden actually does: storing ciphers (encrypted vault items), folders (private groupings), collections (org-shared groupings), and attachments (encrypted files attached to ciphers). Every cipher is end-to-end encrypted on the client; the server is intentionally blind to the contents.
Where the code lives
| Layer | Path |
|---|---|
| Domain | src/Core/Vault/ |
| API surface | src/Api/Vault/ |
| SQL schema | src/Sql/dbo/Tables/Cipher.sql, Folder.sql, Collection.sql, CollectionCipher.sql, Attachment.sql |
| Stored procedures | src/Sql/dbo/Stored Procedures/Cipher_*.sql, Collection_*.sql, Folder_*.sql |
| EF mappings | src/Infrastructure.EntityFramework/Vault/ |
| Authorization | src/Core/Vault/AuthorizationHandlers/ (joint ownership with Admin Console) |
Key abstractions
| Type | Path | Description |
|---|---|---|
Cipher (entity) |
src/Core/Vault/Entities/Cipher.cs |
The encrypted vault item. Type-tagged as Login, SecureNote, Card, Identity, SshKey, or Fido2Key. |
CipherDetails |
src/Core/Vault/Models/Data/CipherDetails.cs |
Read model: cipher + per-user permissions (view, edit, manage). |
ICipherService / CipherService |
src/Core/Vault/Services/{ICipherService.cs, Implementations/CipherService.cs} |
1,175 lines — save / share / move / soft-delete / restore / bulk operations. |
CiphersController |
src/Api/Vault/Controllers/CiphersController.cs |
The 1,713-line REST controller covering every cipher endpoint. |
Folder |
src/Core/Vault/Entities/Folder.cs |
Personal grouping of ciphers. |
Collection |
src/Core/AdminConsole/Entities/Collection.cs |
Organization-shared grouping of ciphers. |
CollectionCipher |
src/Core/Entities/CollectionCipher.cs |
M-to-N link table between Collection and Cipher. |
Attachment |
(column on Cipher, plus blob storage) |
Encrypted file attached to a cipher. Storage backed by Azure Blob (IAttachmentStorageService). |
How it works
graph TD
Client["Client encrypts payload\n(username, password, etc.)"] --> SaveReq["POST /ciphers"]
SaveReq --> Controller["CiphersController.Post"]
Controller --> Authz["IAuthorizationService\n(can write to org/collections?)"]
Authz --> Service["CipherService.SaveAsync"]
Service --> Repo["ICipherRepository\n(Dapper or EF)"]
Repo --> Db[("Cipher table")]
Service --> Push["IPushNotificationService\nPushSyncCipherUpdate"]
Service --> Event["IEventService\nLogCipherEventAsync(Cipher_Created)"]
Push --> Clients["Other devices update"]
Event --> EvQ[("Events queue")]The big endpoints
GET /sync—SyncControllerreturns the user, their personal ciphers + folders + sends, plus every org membership and the org's full cipher set the user has access to. The most expensive read in the system.POST /ciphersandPUT /ciphers/{id}— create / update a single cipher.POST /ciphers/shareandPOST /ciphers/{id}/share— share an existing personal cipher into an org.POST /ciphers/import— bulk create.POST /ciphers/{id}/attachment/v2— chunked attachment upload via SAS URL to Azure Blob.PUT /ciphers/{id}/restoreandPUT /ciphers/{id}/delete-admin— soft-delete state.POST /ciphers/move— move ciphers across folders / collections.
Permissions model
Authorization happens on three levels:
- JWT scope —
Policies.Applicationfor everyday client calls,Policies.Webfor the web vault. - Resource handlers —
BulkCollectionAuthorizationHandlerand friends insrc/Core/Vault/AuthorizationHandlers/decide whether the caller can view/edit/manage a given cipher based on collection membership and role. - Org policies —
Policyrows can require master-password rotation, restrict personal-vault use, force two-step login, etc.
Soft-delete and restore
Ciphers are soft-deleted by default — Cipher.DeletedDate is set, the row stays. Permanent deletion is a separate endpoint and a Quartz job purges items past the retention window. Restore reverses the soft-delete.
Integration points
- Push — every mutation triggers
IPushNotificationService.PushSyncCipherUpdate(or theFolder/Collectionequivalents). - Events — every mutation logs a
Cipher_Created/Cipher_Updated/Cipher_Deletedaudit event. - Application cache —
OrganizationAbilityis read to decide whether the org is enabled and within seat limits. - Attachment storage —
IAttachmentStorageServicewrites / reads blob storage; URLs are SAS-signed. - Bitwarden SDK — the cipher domain has been partially ported to the Bitwarden Rust SDK (
util/RustSdk/). Thepm-19941-migrate-cipher-domain-to-sdkfeature flag (removed in PR #7457, 2026-04-13) gated the rollout.
Entry points for modification
- Adding a new cipher type → extend
CipherType(src/Core/Vault/Enums/CipherType.cs), updateCipherentity validation, add the matching client decoder in the Web Vault, and updateCiphersControllerrequest validation. - Bulk operations →
CiphersController.PutBulkRestore,PutBulkMoveetc. Use bulk stored procedures; do not loop in C#. - Permissions changes → add a new
IAuthorizationRequirement+ handler undersrc/Core/Vault/AuthorizationHandlers/rather than embedding the check inCipherService. - New bulk operation → add a bulk SQL sproc + EF equivalent + the bulk repo method, then a controller endpoint.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.