I've been using aws-vault for some time. It does one thing well: keep your AWS credentials out of plaintext files on disk, and hand short-lived ones to whatever subprocess actually needs them. It's good software.
The trouble is that AWS credentials are never the only secrets on the machine. There's the Stripe key for the side project. The OpenAI token for the prototype. The database URL for the staging environment that isn't behind SSO yet. The webhook signing secret that one client emailed you. None of these are AWS, so aws-vault won't touch them — and they end up where secrets always end up when there's nowhere good to put them: in .env files lying around the filesystem in plaintext, getting accidentally committed, getting backed up to places they shouldn't be, sitting in ~/Projects/ long after the project is dead.
Some frameworks solve this for the framework. Rails has encrypted credentials and they work well — for Rails. The cases I kept hitting were the ones outside that boundary: an OpenTofu run that needs a provider token, a one-off Python script that talks to a vendor API, a Make target that wraps a psql against a managed database. The Rails app is fine. Everything around it is where the plaintext .env files breed.
I wanted the aws-vault posture for all of that. So I built one.
Envault is a small Go CLI that manages encrypted profiles of environment variables — AWS keys, API tokens, anything — and injects them into a subprocess on demand. It's public today, MIT licensed.
envault add stripe-prod STRIPE_SECRET_KEY=sk_live_...
envault exec stripe-prod -- ./run-migration.sh
The secrets live in an AES-256-GCM encrypted vault file (Argon2id for key derivation, OWASP parameters) or in the OS keyring — macOS Keychain, Linux libsecret — your choice. They never touch disk in plaintext. They exist in the child process's memory for as long as the child runs, and then they're gone.
A few things I wanted that aws-vault didn't give me, and that envault does:
- Profile inheritance. A
baseprofile with shared region and tags; adevprofile that inherits from it and overrides what it needs. - TTL on profiles. Mark a profile as expiring after 8 hours, or 7 days. If it's expired,
execrefuses to run and tells you to refresh. Useful for credentials you rotate. - AWS role assumption still works. If a profile has
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, andAWS_ROLE_ARN, envault calls STSAssumeRolebefore injecting — the subprocess gets short-lived credentials, the long-term keys never leave the vault. - Two backends. Encrypted file by default, keyring if you prefer the OS to hold the key.
It's small on purpose. It does what aws-vault does, plus the rest of the secrets you actually have. If that sounds useful:
go install github.com/Wa-Constellation/envault@latest
Source, issues, and the security policy are at github.com/Wa-Constellation/envault. Feedback welcome.
Thomas Riboulet is a Fractional VP of Engineering working with European tech companies. He writes about engineering leadership, team structure, and sustainable delivery at insights.wa-systems.eu.