Skip to main content

envault

Client-side envelope encryption for files using AWS KMS, with DynamoDB state tracking and a full audit trail.

CI PyPI Python License

Beta Software — This project is under active development and is not yet recommended for production use. APIs, CLI flags, and storage formats may change between releases. Use at your own risk.


How it works

  • Files are encrypted locally using AES-256-GCM via the AWS Encryption SDK
  • The data encryption key (DEK) is wrapped by your KMS customer-managed key (CMK) — plaintext never leaves your machine
  • Encrypted files are stored in S3; state and audit events are tracked in DynamoDB
  • Decryption requires AWS credentials with kms:Decrypt on the CMK

Installation

pip install envault-cli

Requires Python 3.10+.


Quick start

# Set required environment variables
export ENVAULT_KEY_ID=alias/my-kms-key
export ENVAULT_BUCKET=my-encrypted-files-bucket
export ENVAULT_TABLE=envault-state
# Accounts trusted to have encrypted your data — required for every read
export ENVAULT_ALLOWED_ACCOUNT_IDS=123456789012

# Encrypt a file
envault encrypt ./secret.txt --tag project=finance

# Check state
envault dashboard

# Run a command with the secret in its environment — never written to disk
envault exec -s secret.txt=API_TOKEN -- ./my-app

# Or decrypt to a file, by filename or SHA256 hash
envault decrypt secret.txt -o ./

Configuration

All config via environment variables — no config files with secrets.

Variable Required Default Description
ENVAULT_KEY_ID Yes KMS key alias (e.g. alias/my-key)
ENVAULT_BUCKET Yes S3 bucket for encrypted files
ENVAULT_TABLE Yes DynamoDB table name
ENVAULT_ALLOWED_ACCOUNT_IDS For reads Comma-separated AWS account IDs trusted to have encrypted the data. Required by decrypt, exec, and rotate-key: it constrains KMS discovery so a ciphertext header cannot name a key outside your control.
ENVAULT_REGION No us-east-1 AWS region
ENVAULT_AUDIT_TTL_DAYS No 365 Days to retain audit events

CLI reference

# Encrypt a file (or directory) and store in S3
envault encrypt INPUT_PATH [--tag KEY=VALUE]... [--force]

# Run a command with secrets supplied in memory, never on disk
envault exec -s IDENTIFIER=VAR [-f IDENTIFIER=VAR]... [--clean-env] -- COMMAND [ARGS]...

# Decrypt by filename or SHA256 hash
envault decrypt IDENTIFIER [-o OUTPUT_DIR] [--version N]

# List all encrypted/decrypted files
envault status [--state encrypted|decrypted|all]

# Show state for a specific file
envault status --file SHA256

# View audit events
envault audit [--since YYYY-MM-DD] [--file SHA256]

# Summary dashboard
envault dashboard

# Re-encrypt all files with a new KMS key
envault rotate-key --new-key-id alias/new-key [--dry-run]

# Migrate from legacy output.json (NDJSON format)
envault migrate FROM_PATH [--dry-run]

Running commands with secrets

envault exec decrypts into a process and nothing else. There is no temporary file to clean up and no plaintext left behind if the command crashes.

# As an environment variable
envault exec -s db.env=DATABASE_URL -- ./server

# As a file, for programs that insist on a path (certs, keystores, kubeconfigs)
envault exec -f server.pem=TLS_CERT -- curl --cert {TLS_CERT} https://api.internal

# Both, from a minimal environment that drops your ambient AWS credentials
envault exec --clean-env -s db.env=DATABASE_URL -f server.pem=TLS_CERT -- ./server

--file writes the plaintext to an anonymous in-memory descriptor (memfd), seals it once the checksum and encryption context verify, and passes $VAR as /proc/self/fd/N. No directory entry ever exists, so no other process can open it by name. A {VAR} token anywhere in the command is replaced with that path.

Before decrypting, envault disables core dumps and sets PR_SET_DUMPABLE=0 so a same-uid process cannot ptrace it or read /proc/<pid>/mem while the secret is in flight, and attempts to lock its pages out of swap.

What this does not protect against. PR_SET_DUMPABLE is reset by execve, so it covers the envault process, not the command it launches — a same-uid attacker can still read that child's /proc/<pid>/environ. Nothing here stops root. CPython cannot reliably zero plaintext it has already copied, so --file is the stronger mode wherever the consumer accepts a path.

Access is recorded in the audit trail, attributed to the calling AWS principal, before the command starts. If that write fails the command does not run: an unlogged secret read is treated as a failure, not a warning.


AWS infrastructure (CDK)

The infra/cdk/ directory contains a CDK Python stack that provisions:

  • KMS CMK with automatic annual key rotation
  • S3 bucket — versioned, SSE-KMS, block-public-access enforced
  • DynamoDB table — on-demand billing, KMS encryption, PITR, all GSIs
  • IAM managed policy — least-privilege, ready to attach to users/roles
cd infra/cdk
pip install -r requirements.txt
cdk synth
cdk deploy

Development

# Install with dev dependencies
python -m venv .venv
source .venv/bin/activate
PIP_USER=false pip install -e ".[dev]"

# Run unit tests (no AWS credentials required)
pytest tests/unit/ -v

# Lint and type check
ruff check src/ tests/
mypy src/envault/

Security

  • KMS alias only in config — ARN is never stored or committed
  • detect-secrets pre-commit hook prevents credential leaks
  • Encryption context and SHA256 checksum are both verified before any plaintext is written or handed to a command — a substituted ciphertext never materialises
  • KMS discovery is constrained to explicitly trusted account IDs, so a ciphertext header cannot direct a decrypt at a key outside your control
  • DynamoDB events are append-only, enforced by a write condition rather than convention, and record the AWS principal responsible
  • S3 bucket policy enforces SSE-KMS on all objects
  • envault exec keeps plaintext out of the filesystem entirely (see above for the limits)

License

Apache 2.0 — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

envault_cli-0.2.0.tar.gz (136.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

envault_cli-0.2.0-py3-none-any.whl (41.5 kB view details)

Uploaded Python 3

File details

Details for the file envault_cli-0.2.0.tar.gz.

File metadata

  • Download URL: envault_cli-0.2.0.tar.gz
  • Upload date:
  • Size: 136.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for envault_cli-0.2.0.tar.gz
Algorithm Hash digest
SHA256 434efb2361b6c95e94eb22dec1c5e6ffd05d5b876dba2791cdfea90d34b3bb11
MD5 0cfa4d08725fb11c37f1f8c57b536629
BLAKE2b-256 22fd6d65a7366f5ffd00bccae2d51272def9bfc05eb81c481a400f8da0bcf88b

See more details on using hashes here.

Provenance

The following attestation bundles were made for envault_cli-0.2.0.tar.gz:

Publisher: publish.yml on Specter099/envault-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file envault_cli-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: envault_cli-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 41.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for envault_cli-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 15018257b41ef496d648d496dac4e5eae1e64fc7b1729c73a317c523be60b447
MD5 c1b6635c6cc63036a4bb617a91f5d2cf
BLAKE2b-256 6235f3bfe688a014d4a448f2bc2d62cec57ea4759f6eb676ce9cda97d10f3cef

See more details on using hashes here.

Provenance

The following attestation bundles were made for envault_cli-0.2.0-py3-none-any.whl:

Publisher: publish.yml on Specter099/envault-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.2

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page