Use promo code BETATEST1 for full access
seekrit
← all posts

Should your coding agent be able to read your .env?

Security

No — and by default, most of them can. A coding agent works in your project directory, your project directory contains a .env, and a .env is production credentials in plaintext. The agent doesn't need to be malicious for that to go wrong: it reads the file to understand your config, and now your Stripe key is in a transcript that gets logged, retained, and — as three vendors learned in 2026 — sometimes talked out of the model by whoever can write to its input.

You can block the reads, and you should. But blocking is the shallow half of the fix, so this post covers both halves.

Blocking reads, per tool

Claude Code takes deny rules in .claude/settings.json. This stops the Read tool from opening the files:

{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)"
    ]
  }
}

Cursor uses .cursorignore in the project root — add .env and .env.* and the files are excluded from indexing and access.

GitHub Copilot offers content exclusions, configured at the repository or organization level rather than in a project file.

Do this today; it costs five minutes. Then look at what it doesn't cover.

Why blocking isn't enough

Agents run shell commands. A deny rule on the file-read tool doesn't stop cat .env, grep -r "sk-" ., or a test runner that prints its environment on failure. You can deny shell patterns too, but you're now enumerating every way a Unix system can read a file, and the agent legitimately needs the shell.

The agent isn't the only reader. The same file is readable by every npm postinstall script, every MCP server you've configured, and every dependency of your dev server. Fencing one reader leaves the value on disk for all the others.

.env files multiply. .env.local, .env.production, the copy in the other service's directory, the one a teammate sent over Slack. Ignore rules are per-file, per-tool, per-machine; the sprawl isn't.

Some agents skip .env — and still need the values. The Claude Agent SDK doesn't read .env files at all, which protects it from the file and leaves you finding another way to configure the process it runs.

The setup where there's nothing to block

Delete the file and inject at spawn instead. Secrets live encrypted in seekrit; seekrit run decrypts them locally and puts them in the child process's environment, exactly where your code already looks:

seekrit secrets import .env --app storefront --env development
git rm --cached .env
seekrit run -- npm run dev

Now the working directory contains no credentials. The agent can read every file in the repo — there's nothing sensitive to find. No deny rules to maintain, nothing for a postinstall script to scoop up, and rotation happens in one place instead of everywhere the file was copied. Local overrides still work: seekrit run layers a local .env over the managed set, so a .env.local with one dev value keeps its job. The dotenv guide walks the migration.

One habit to pair with it: the values are now in the process environment, so a printed process.env still leaks. If the agent needs to run your app, seekrit run -- npm test gives the test process its secrets while the agent sees only stdout — and seekrit's MCP tools do the same for arbitrary commands via run_command.

When the agent itself is the threat model

Everything above assumes an editor agent working under your supervision. An autonomous agent with a shell can run seekrit run -- env like anything else, so spawn-time injection isn't a boundary against it. For that case the credential has to stay outside the process entirely — a placeholder in the environment and a credential broker substituting the real value at the network edge. The five-level ladder covers when to make that jump.

The short version

  1. Add deny rules for .env in every agent you use — cheap, do it now.
  2. Move the values out of the file: seekrit secrets import .env, then delete it. This is the fix that doesn't depend on tool-by-tool rules.
  3. Rotate anything that was in the file while agents could read it.
  4. If the agent runs unsupervised, keys out of the process too — use the proxy.