vcon-server

Assurance case

Why vcon-server's security requirements are met: the threat model, the trust boundaries, how the design principles are applied, and how the common weaknesses are countered.

The claim: a vCon stored in vcon-server is readable only through a key allowed to read it, and no copy of the data at rest, alone, gives anyone its contents. This page sets out why that holds. The mechanisms are described on the security page; this page argues from them.

Threat model

What is protected:

  • the vCons each tenant stores, and their earlier versions,
  • the keys that open them: the master key, each tenant key and each data key,
  • the API tokens that grant access, and the audit records of that access.

Who the server defends against:

  • a client on the network without a valid key, or with a key used beyond its scopes;
  • a tenant reaching for another tenant's data;
  • an operator with an operator key, who manages tenants and keys but has no reason to read a vCon;
  • someone who obtains the data directory, a backup of it, or the request log, without the master key;
  • with S3 storage, someone who reads the bucket or holds the server's S3 key;
  • crafted input: a malformed vCon, an oversized or deeply nested body, or a hostile request.

Out of scope: an attacker who holds both the data and the master key at the same time, or who controls the host while the server runs. The table in What each theft gives says what each stolen part gives.

Trust boundaries

BoundaryWhat crosses itWhat guards it
Network to serverevery HTTP requestTLS only (rustls, TLS 1.2 and 1.3); a bearer key on every request, checked against its scopes
Tenant to tenantnothingeach key belongs to one tenant; each tenant has its own tenant key and catalog
Operator key to vConsnothingan operator key holds only admin and can never reach a vCon
Server to disksealed bodies, wrapped keys, catalogsAES-256-GCM bound to tenant, uuid and version; SQLCipher catalogs; the master key is never stored by the server
Server to an S3 bucketsealed bodies only, named by random ids; no key and no uuidTLS, with the certificate checked against the system's authorities or storage.s3.ca_file; the same AES-256-GCM sealing; a claim that keeps each bucket prefix to one data directory
Server to swap and core dumpsnothingall memory locked (mlockall), core dumps off, each key in its own locked page
Server to browserthe console's pages and the data it showsa content-security policy allowing only the console's own script; data shown as text
Host operator to datacommands run as the service accountthe master key file (mode 0400) and the data directory (mode 0700), owned by that account, as Getting started sets them up

Secure design principles

  • Deny by default, complete mediation: every request needs a key, and every route checks the key's scopes; a request without the scope is refused with forbidden and recorded.
  • Least privilege: five tenant scopes (write, read, delete, legal, audit), each given only where needed; an operator key cannot read a vCon or make another operator key (Tenants and keys).
  • Separation: each tenant's data is sealed under its own keys, and a sealed body moved to another tenant, uuid or version does not open.
  • Economy of mechanism: one cryptographic library (AWS-LC, through aws-lc-rs) and one construction for every encryption (AES-256-GCM with a random nonce and the context bound in).
  • Fail safe: the server refuses to start if it cannot lock its memory, and refuses writes once a wrapping key nears the NIST nonce limit, until the key is rotated.
  • Accountability: every request is recorded in the audit log (Audit logs); the request log holds only method, route template, status and timing.

Common weaknesses countered

WeaknessCountered by
Missing or broken authentication (CWE-287, CWE-306)a bearer key on every request; tokens stored only as SHA-256 and compared by it
Missing authorization (CWE-862, CWE-863)scopes checked on every route; tenant keys cannot hold admin; operator keys cannot reach vCons
Cleartext storage or transmission (CWE-312, CWE-319)sealed bodies and encrypted catalogs on disk; TLS only on the wire
Weak or misused cryptography (CWE-327, CWE-330)AES-256-GCM, HKDF-SHA256 and SHA-256 from AWS-LC; keys and nonces from its random generator; no MD5, SHA-1, RC4 or DES
Sensitive data in logs (CWE-532)an audit record holds no vCon content, no token and no client address; the request log holds the route template, never the path (Audit logs)
SQL injection (CWE-89)catalog statements bind their values as parameters; the one statement built as text is a PRAGMA given a version number the catalog holds
Cross-site scripting (CWE-79)the console shows server data as text, under a content-security policy with no inline code
Memory-safety errors (CWE-119, CWE-416)Rust; the unsafe code is confined to system calls (memory locking, core-dump limits, file locking, an access check) and SQLCipher's key calls, and the tests run under AddressSanitizer, the locked-memory code under Miri
Uncontrolled resource use (CWE-400, CWE-674)request bodies bounded by limits.body, gzip inflation by limits.inflated, JSON nesting and signed layers to 64 deep
Malformed input (CWE-20)the vCon reader refuses anything outside the format, with a problem document naming why

Evidence

  • The tests, run on every push and pull request (Development), with the test for each change written first.
  • AddressSanitizer over the tests and Miri over the locked-memory code (sanitizers.yml).
  • Twelve fuzz targets, over the vCon reader, the request and query parsers, the configuration, tokens, ids, retention and the sealed format, in CI and in ClusterFuzzLite (fuzz/fuzz_targets).
  • CodeQL's security queries and clippy with warnings as errors, on every push and pull request. Code scanning's CodeQL check is required on main: a pull request with a new CodeQL alert in the code it changes does not merge until the alert is fixed or dismissed with its reason.
  • The security policy for reporting what this page has missed.

Source of this page: website/content/docs/assurance-case.md