Threat Model
# Threat model
The CLI encrypts complete files with the age executable's native recipient format.
Team members and CI each supply their own age public key. The private identity remains
local. Env Vault runs no key exchange or hosted credential store.
Ciphertext can be shared in a repository without exposing values to people who lack a
matching private key. Names and contact assignments in .envvault.json are plaintext.
Encryption is authenticated by age; malformed ciphertext and wrong keys fail closed.
We implement no cryptographic primitive. Optional offline identity recovery uses the
unaltered PhotoSafe crypto_core module in scripts/recovery.py, separate from the CLI.
A compromised endpoint, malicious child command, debugger, process dump, swap capture
or stolen private key can expose values. Python cannot reliably zero all copies of
plaintext from memory. Processes under the same account may inspect the environment.
The child controls its stdout/stderr; Env Vault does not promise to sanitize child logs.
Removing a recipient only applies to newly encrypted files. Revoke credentials at their
provider as well; previous commits and backups remain readable with the old key.
Dotenv syntax is intentionally strict: UTF-8, single-line literal values, optional
matching quotes, full-line comments and optional export prefix. No expansion, escapes,
multiline values or command substitution. Duplicate keys fail. Inline # stays literal.
Encrypted files and config updates are atomic individually, not a combined transaction;
back up config before rotation and re-run inventory after an interrupted write.
The pre-commit hook inspects the staged version, uses gitleaks built-in rules with repo
allow comments disabled, and fails on scanner errors. Pattern detection cannot find
all credentials. Hooks can be bypassed; use the same check in CI. No values appear in
hook output. Install gitleaks separately to keep the base CLI dependency small.
The web tool accepts names only, never .env uploads. Requests may still pass through a
reverse proxy: disable request-body logging. Inventory evidence is private; /verify
shows only integrity. Pin the signing public-key fingerprint out of band. Rotation of
the signing key requires an explicit trust update; a valid embedded key proves no identity.