Encrypt, decrypt, edit, and load .env files from Python without committing
plaintext secrets.
dotenv-encrypt uses AES-256-GCM for authenticated encryption and derives keys
from a passphrase with scrypt. New files include a random salt, a random nonce,
and authenticated encryption metadata.
pip install dotenv-encryptFor local development:
python -m pip install -e ".[dev]"
pytestfrom dotenv_encrypt import load_enc_env, unload_enc_env
load_enc_env(".env.enc")
# os.environ now contains the variables from .env.enc
unload_enc_env()When no passphrase is supplied and DOTENV_ENCRYPT_KEY is unset,
dotenv-encrypt prompts securely with getpass. This is the recommended local
usage because the passphrase is not stored in source code.
Read and write encrypted dotenv files directly:
from dotenv_encrypt import read_encrypted_env, write_encrypted_env
write_encrypted_env(
{"API_KEY": "secret", "DEBUG": "false"},
".env.enc",
)
env = read_encrypted_env(".env.enc")An explicit passphrase= argument is available for controlled integrations and
tests. For automation, prefer a protected DOTENV_ENCRYPT_KEY environment
variable over hard-coded source values.
The CLI intentionally avoids passphrase command-line flags, because command-line
arguments can leak through shell history and process listings. Set
DOTENV_ENCRYPT_KEY for automation, or let the CLI prompt securely.
dotenv-encrypt
dotenv-encrypt help show
dotenv-encrypt encrypt .env -o .env.enc
dotenv-encrypt show .env.enc
dotenv-encrypt show .env.enc --full
dotenv-encrypt set API_KEY "secret" .env.enc
dotenv-encrypt unset API_KEY .env.enc
dotenv-encrypt merge
dotenv-encrypt merge .env .env.enc
dotenv-encrypt decrypt .env.enc -o .env.local
dotenv-encrypt decrypt --overwriteRunning dotenv-encrypt without arguments prints the command overview.
dotenv-encrypt help <command> prints help for one command.
encrypt asks for confirmation before replacing an existing output file. Use
encrypt --force for non-interactive replacement in scripts.
decrypt refuses to replace existing plaintext output unless --overwrite or
--force is supplied.
show masks values by default in abc...xyz style. show --full prints full
plaintext values.
--delete-plaintext removes the plaintext file after a successful operation by
unlinking it. It is not secure erasure and does not remove copies from backups,
snapshots, filesystem journals, SSD wear-leveling storage, or other locations.
- Encryption is AES-256-GCM with a fresh 96-bit nonce for every write.
- Passphrases are stretched with scrypt and a fresh 128-bit salt per file.
- File metadata is authenticated with AES-GCM additional authenticated data.
- Output files are written with
0600permissions where the platform supports POSIX modes. - Encrypted files are written through an atomic same-directory replace to avoid truncating an existing store on write failure.
- Secret values are masked by default.
show --fullshould be used only when plaintext output is required.
dotenv-encrypt protects the contents of an encrypted .env.enc file only
while the attacker does not also have the passphrase or the decrypted
environment values. It is a file-at-rest protection tool, not a runtime
sandbox or secret manager.
- Offline file reads: an attacker gets a copy of a repository, laptop
backup, deployment bundle, container image, or disk contents and can read
.env.enc, but cannot access the passphrase. - Accidental secret commits:
.env.enccan be committed without exposing the plaintext values that would have appeared in.env. - Simple online file stealers: malware or an intrusion grabs project files from disk but does not read process memory, process environments, shell history, terminal input, CI logs, or password manager contents.
- Stopped or unloaded apps: an online attacker gets file access after the
application has stopped, before the application has started, or after
unload_enc_env()has been called and no other copy of the plaintext values remains in the process. - Tampering with encrypted files: AES-GCM authentication detects wrong passphrases and modified ciphertext or authenticated metadata.
- Attackers with the passphrase: anyone who knows
DOTENV_ENCRYPT_KEY, saw the passphrase being typed, read it from a password manager, or found it in CI configuration can decrypt the file. - Runtime memory or environment theft: if an application has already loaded
the variables, an attacker who can read process memory,
/procenvironment data, crash dumps, debugger output, or equivalent OS/runtime state can obtain the plaintext values. - Malicious code running in the same process: dependencies, plugins, or app
code can read
os.environafterload_enc_env()has populated it. - Shell, log, and history leaks: decrypted values printed by an application,
dotenv-encrypt show --full, debug logs, traces, shell history, copied plaintext.envfiles, and CI output are outside the encryption boundary. - Compromised hosts: if an attacker controls the machine while secrets are being decrypted or used, encryption at rest cannot keep those runtime secrets private.
- Weak passphrases: scrypt slows guessing, but it cannot save a short, reused, or leaked passphrase from offline brute force.
- Rollback to a valid prior file: AES-GCM detects modification, but a
previously valid
.env.enccan be restored unless an external deployment, backup, or versioning process detects the rollback.
- Keep the passphrase out of source control, logs, command-line arguments, and issue trackers.
- Prefer interactive prompts locally and protected CI secrets or GitHub environment secrets in automation.
unload_enc_env()should be called when a long-running process no longer needs the values. Decrypted values should not be copied into other long-lived globals.- Treat
show --fullanddecryptas sensitive operations. Plaintext output and plaintext files should be short-lived and handled like any other secret.