Open-Source Wikis

/

Bitwarden Server

/

Features

/

Vault & ciphers

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 /syncSyncController returns 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 /ciphers and PUT /ciphers/{id} — create / update a single cipher.
  • POST /ciphers/share and POST /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}/restore and PUT /ciphers/{id}/delete-admin — soft-delete state.
  • POST /ciphers/move — move ciphers across folders / collections.

Permissions model

Authorization happens on three levels:

  1. JWT scopePolicies.Application for everyday client calls, Policies.Web for the web vault.
  2. Resource handlersBulkCollectionAuthorizationHandler and friends in src/Core/Vault/AuthorizationHandlers/ decide whether the caller can view/edit/manage a given cipher based on collection membership and role.
  3. Org policiesPolicy rows 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 the Folder / Collection equivalents).
  • Events — every mutation logs a Cipher_Created / Cipher_Updated / Cipher_Deleted audit event.
  • Application cacheOrganizationAbility is read to decide whether the org is enabled and within seat limits.
  • Attachment storageIAttachmentStorageService writes / reads blob storage; URLs are SAS-signed.
  • Bitwarden SDK — the cipher domain has been partially ported to the Bitwarden Rust SDK (util/RustSdk/). The pm-19941-migrate-cipher-domain-to-sdk feature 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), update Cipher entity validation, add the matching client decoder in the Web Vault, and update CiphersController request validation.
  • Bulk operations → CiphersController.PutBulkRestore, PutBulkMove etc. Use bulk stored procedures; do not loop in C#.
  • Permissions changes → add a new IAuthorizationRequirement + handler under src/Core/Vault/AuthorizationHandlers/ rather than embedding the check in CipherService.
  • 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.

Vault & ciphers – Bitwarden Server wiki | Factory