vcon-server

Security

The key hierarchy, what is encrypted with what, how the process protects keys in memory, and what an attacker gets from each thing they might steal.

Keys

master key (32-byte file, never stored by the server)
├── wraps each tenant key            AES-256-GCM, bound to the tenant id
│   ├── wraps each version's data key AES-256-GCM, bound to tenant, uuid and version
│   │   └── seals that version's body AES-256-GCM, bound to tenant, uuid and version
│   └── derives the tenant catalog key HKDF-SHA256
└── derives the server catalog key     HKDF-SHA256 → server.sqlite
  • Every key is 256 bits from the system's random source.
  • Every encryption uses AES-256-GCM with a random 96-bit nonce, and binds its context in the associated data: a sealed body moved to another tenant, uuid or version does not open.
  • A wrapping key is retired before it can wrap 2^32 keys, the limit NIST SP 800-38D sets for random nonces: writes are refused with limit-reached (or master-key-limit) until the key is rotated.
  • Catalogs are SQLCipher 4 databases keyed with HKDF-SHA256 of their parent key (no salt, info vcon-server/v1 catalog), with secure_delete on.
  • The cryptography is AWS-LC, through aws-lc-rs.

In memory

  • At start the process locks all its memory (mlockall), so no key or body is ever written to swap, and refuses to start if it cannot.
  • It turns core dumps off (RLIMIT_CORE 0 and not dumpable), so a crash writes no memory to disk.
  • Each key lives in its own locked page, excluded from core dumps, and is zeroed when dropped.

On the wire

TLS only, via rustls with its safe default protocol versions (TLS 1.2 and 1.3), HTTP/2 and HTTP/1.1. Tokens are compared by their SHA-256; the server never stores a token. With its objects in an S3 bucket, the server reaches the bucket over TLS too, with the certificate checked against the system's authorities or those in storage.s3.ca_file.

In the browser

The console holds the key it signs in with in page memory only, shows everything the server sends as text, and is served with a content-security policy that allows only its own script, no inline code and no framing.

What each theft gives

StolenGives
The data directory alonenothing readable: sealed files and encrypted catalogs
A backup of the data directorythe same, until someone also has the master key of that time
The master key alonenothing without the data
Botheverything they cover, as of when they were taken
A tenant keyits scopes, for its tenant, until revoked
An operator keytenant and key management over HTTP; never any vCon, and never a new operator key
The request logmethod, route template, status and timing only
The bucket of S3 storagesealed objects only, named by random ids: no vCon, no uuid, and no key that opens one
The S3 secret keythe same objects, and the power to delete them: no vCon, but a deleted object is a version lost, so keep the key as a secret and give it access to one bucket

Key rotation shortens "as of when they were taken": after it, old copies of the data cannot be opened with the new keys, and the old ones are destroyed.

Reporting a vulnerability

Please report it privately through GitHub's security advisories for the repository, not in a public issue.

Source of this page: website/content/docs/security.md