The Problem

.env files in version-controlled projects routinely expose secrets—API keys, database credentials, tokens—in plain text. A single git add ., a misplaced screen share, or an AI coding agent reading project files can leak these values. The repository addresses this by encrypting .env values in place, prefixing encrypted entries with encrypted: so they remain in the project directory without exposing raw secrets.

What This Does

envcrypt provides AES-256-GCM authenticated encryption for .env files. The Rust library envcrypt-lib (envcrypt-lib/src/lib.rs) handles the core cryptographic operations, while the Python CLI envcrypt (envcrypt/src/main.rs) provides the command-line tool. The Python loader module (envcrypt-py/envcrypt/loader.py) ties key derivation and file loading together. Encrypted values carry the encrypted: prefix; plain values pass through unchanged. The key resides in ~/.envcrypt.yaml as a 64-character hex-encoded 32-byte value. The repository has 3 projects: envcrypt-py (7 files, 5 code), envcrypt-lib (2 files, 1 code), and envcrypt (2 files, 1 code).

How It Is Wired

Execution begins at the CLI entry point envcrypt/src/main.rs, which dispatches init, encrypt, decrypt, encrypt-value, decrypt-value, and status subcommands. The encrypt and decrypt functions are each called from 14 places across the codebase, making them the widest-blast-radius operations. Key derivation flows through from_key (called from 8 places) and from_config (called from 5 places), both of which can raise EnvcryptError (raised from 6 places). Loading a .env file routes through EnvcryptLoader::from_config or EnvcryptLoader::from_key, then calls load, which invokes load_from_string (called from 4 places), which in turn calls decrypt and may raise EnvcryptError. The test file envcrypt-py/tests/test_loader.py exercises key generation length, uniqueness, hex validity, and invalid-key scenarios, calling generate_key twice. A single encryption hop touches the filesystem (read/write of .env and .env.encrypted); decryption follows the reverse path. No CI/CD pipeline is configured, and no lockfile accompanies the Cargo manifests, meaning transitive dependency versions are not pinned for reproducibility.

How To Use It

Setup: Install the CLI via cargo install --path envcrypt or add envcrypt-lib as a path dependency in Cargo.toml. For Python usage, the package lives in envcrypt-py; install with pip install -e . from that directory.

Configuration: A key must exist at ~/.envcrypt.yaml in the format key: "64-character-hex-encoded-key...". Alternatively, pass a hex key string directly to EnvcryptLoader::from_key.

Running it:

  • Initialize a key: envcrypt init --generate or envcrypt init --key "your-64-character-hex-key-here..."
  • Encrypt a .env file: envcrypt encrypt .env --in-place or envcrypt encrypt .env -o .env.encrypted
  • Decrypt: envcrypt decrypt .env.encrypted --in-place or envcrypt decrypt .env.encrypted -o .env
  • Single value: envcrypt encrypt-value "my-secret" outputs encrypted:base64...; envcrypt decrypt-value "encrypted:base64..." outputs the secret.

Real-World Use

A CI pipeline stores only the encrypted .env.encrypted in version control. On deployment, the Rust service loads the file via envcrypt_lib::EnvcryptLoader::from_config(None)? followed by loader.load(".env"?); decryption happens at runtime, so raw secrets never touch disk in plain text. The Python CLI can similarly decrypt during local development. Plain, non-sensitive values remain unencrypted and pass through transparently.

Code Health & Issues

  • [HIGH] Add a LICENSE - no licence file at the repository root; redistribution rights are undefined, so the code cannot be legally reused in client engagements.
  • [HIGH] Commit a lockfile beside the manifest - Cargo.toml has no lockfile; unlocked ranges allow transitive code to differ between tested and shipped artifacts.
  • [MEDIUM] Enable Dependabot or Renovate - 4 manifest(s) with no update bot configured; published advisories remain unpatched without manual audits.

The Bottom Line

The code functions as intended—AES-256-GCM encryption, CLI and library interfaces, and .env workflow all work. However, three hygiene gaps limit production readiness: no license blocks reuse, missing lockfile risks supply-chain drift, and no dependency update automation means vulnerabilities go unpatched. Teams that need to ship encrypted .env files and already manage key rotation will find it practical; those requiring legal clearance or strict reproducibility guarantees should address the license and lockfile gaps first.