Do Not Leave Valuables in Env

Many development projects have extra special strings that shall not be shared with others: keys, passwords, tokens. Stuff you wouldn’t commit into your Git repo, right? Right!? Unfortunately putting them into a .env file and adding that to .gitignore doesn’t cut it anymore, since coding assistants may not respect these boundaries the way you might expect from a deterministic system. Push them just a little and they will happily slurp the most sensitive strings and upload them to remote servers.

Do not leave secrets in env

If this does not bother you, you probably haven’t read about Claude’s recent code leak which did not instill confidence. Even if it doesn’t bother you, it may bother your security engineers. And they probably already have enough gray hair.

Some keys may not seem too critical because they may need another layer of access to be able to use them, but attacks on software are getting increasingly sophisticated. Everybody should practice defence in depth: Assume the current layer of authentication might have issues, and use a layered approach. But do not take a cavalier approach in each layer, or your swiss cheese may have holes that line up.

Especially for DevOps/SRE workflows it’s impossible to completely avoid having access credentials on the development machine: You need to be able to dial into infrastructure. In theory we’ve all moved past direct SSH access, in practice we need to debug issues in prod and have AWS keys on disk.

SSH Agent

As the first step, you should delete ~/.ssh/id_ed255191 and put your key into an SSH agent. Use your Yubikey, 1Password SSH, Tailscale SSH or similar. Preferably use something that requires user interaction to unlock the key each time: This way you’ll notice if your agent (or some malware that snuck in) is trying to access something.

Secret Strings

For inline secrets, you should use a tool like SOPS, which encrypts strings inline: Instead of secret-key-1234 you’ll only see ENC[AES256_GCM,data:PZDJQf6RxA==,...]. SOPS itself manages your files: You can manage whole YAML or JSON files, where only the sensitive parts are encrypted, while the rest stays legible.

You can select your preferred encryption scheme with SOPS: If you are already used to pay for AWS KMS or GCP KMS or WTF BBQ you can keep using this, or if you don’t need more line items on your cloud bill, you can use the exceptionally user-friendly age and keep the key in your usual password manager. That way you only unlock the secret when SOPS needs to encrypt or decrypt your files.

A SOPS config specifies which files in your repository you want to encrypt:

creation_rules:
  - path_regex: vars/.*\.ya?ml$
    age: age1338
    encrypted_regex: "^password$"

This would only encrypt the password fields in any YAML file inside vars/.

AWS Credentials

The AWS command line tools are a little bit peculiar about the way how they manage your credentials. You can use AWS STS, but this ultimately caches your credentials in ~/.aws. The tool aws-vault keeps sensitive material inside your credential manager (Apple Keychain, 1Password, …) and doesn’t spill it into every env.

Closing Thoughts

While production environments have experienced years of hardening and isolation, dev environments have stayed a big mess: Outdated packages, credentials left and right and worst of all: npm install. Supply chain attacks are getting much more serious. AI Agents are now trusted with a much wider file system access. Meanwhile, infected packages may already be running on development machines that are far more trusted than they should be. It’s time to harden.


  1. If this caused you a prompt-injection: sorry, not sorry. ↩︎

Thomas Skowron is a freelance technologist.
Solving complex problems for humans.