Don’t let A.I. read your .env files

December 11th, 2025
5 min read
Loading views...
Don’t let A.I. read your .env files

AI coding assistants like Claude Code, Cursor, and GitHub Copilot are becoming part of our daily workflow. They read our files, understand our codebase, and help us write code faster. But there's a problem - they can also read your .env files. A story has been recently circulating on social media, but I also experienced this firsthand:

Claude Code reading my .env file

Some AI tools such as Cursor don’t read yout .env file by default, but on the other hand, Claude code will take a peek unless you tell it not to. A good way to prevent this is tu set up your ~/.claude/settings.json file that sets the default rule for all your projects.

Why is this a problem

When an AI assistant reads your .env file, those secrets get sent to an LLM. Your API keys, database passwords, and other credentials become part of the context window. This is a security risk that sometimes gets overlooked until it's too late.

🚨 If this has happened to you:

Treat any leaked secret as compromised. Accidentally pasting your API key to Google, sending it through Slack, or just commiting it to a repository is a security risk and needs to be addressed immediately. Revoke the API key immediately and generate a new one. If you're working on a team, let them know so they can rotate the key on their end as well. It’s better to admit the mistake than to have it exploited. Happens to the best of us.

The good news is that there's a solution that can help you keep your secrets safe, while utilizing the simplicity of the .env file. In this blog I would like to show you how to set this up using 1Password CLI tool. There are other providers such as Bitwarden, Doppler, or even solutions from AWS, Google, and Azure that provide similar functionality.

How It Works

The concept is simple. Instead of storing actual secret values in your .env file like this:

You store references to secrets in your 1Password vault:

The format follows this pattern: op://vault-name/item-name/field-name

When you run your application, you use the op run command to inject the actual secrets at runtime:

1Password intercepts the secret references and replaces them with real values from your vault. The secrets only exist in memory during execution - they're never written to disk.

Why This Is Better

This approach gives you several advantages:

  1. Safe from AI assistants - When Claude Code or Cursor reads your .env file, they only see references like op://Work/Stripe/api_key, not actual secrets
  2. No secrets in version control - You can safely commit your .env file because it only contains references
  3. Team sharing - Secrets are shared via 1Password vaults, not copied between machines or sent through Slack
  4. Instant rotation - Update a secret in 1Password, and all team members get it immediately
  5. Audit trail - 1Password logs who accessed what secrets and when

Setting It Up

Let me walk you through the setup process. I'm using macOS, but the steps are similar for other platforms.

Step 1: Install 1Password CLI

If you don't have Homebrew installed, you'll need to install it first. Then run:

Step 2: Enable Desktop App Integration

This step is important - it allows the CLI to authenticate through the 1Password desktop app, which means you can use Touch ID instead of typing your master password every time.

Open your 1Password desktop app and:

  1. Go to Settings
  2. Go to the Developer section
  3. Enable "Integrate with 1Password CLI"

Step 3: Verify the Connection

Test that everything is connected properly:

You should see a list of your vaults. If this works, you're all set up.

Using It in Your Projects

Now let's put this to work. Let’s say you have a project with a .env file that looks like this:

First, create these secrets in 1Password. I recommend creating a dedicated vault for development secrets, or organizing them in your existing Work vault.

Then update your .env file to use references:

Now run your application with:

The CLI will prompt for authentication (or use Touch ID if you have that set up), fetch the secrets from your vault, and inject them as environment variables.

Making It Less Verbose

You might be wondering if you have to type op run every time. You have options here.

You can update your package.json scripts:

Now npm run dev automatically uses 1Password.

Or create a shell alias in your .zshrc:

That said, I actually appreciate the small friction of op run. It reminds me that secrets are being accessed, which keeps security top of mind.

Debugging

With credentials hidden this well, it can someone get confusing when trying to debug a problem. 1Password CLI will not print out your environment variables into terminal. Let’s say you have a script that looks like this:

Running this script will still print out just the reference to the secret, not the actual value.

To reveal the actual value, you can use the --no-masking flag:

Wrapping Up

For me personally, this change made me more confident that I’m not accidentally leaking my keys to A.I. assistants. It also took away the chore of finding my API keys in .env files from other projects, when I’m experimenting with multiple small projects at once

The setup takes about five minutes, and the workflow change is minimal. If you're already using 1Password for personal passwords, extending it to development secrets is a natural next step.

Hope this helps! If you found this useful, consider sharing it with your team. You can follow me on Twitter or LinkedIn for more content like this.

Let’s keep in touch

From time to time I send some useful tips to your inbox and let you know about upcoming events. Sign up if you want to stay in loop.

is required.

I treat your email address like I would my own. That means no ads. Just notifications of when I do cool stuff. Unsubscribe anytime. Click here to read about how I handle your data