cd /news/ai-agents/your-coding-agent-can-read-your-env-… · home › topics › ai-agents › article
[ARTICLE · art-168878] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=· neutral

Your coding agent can read your .env. Here's how I reduced the risk

A developer documented a method for keeping secrets out of reach of coding agents by moving credential values from project .env files into 1Password and committing only op:// references in an op.env file, then launching apps via 'op run --env-file=op.env -- pnpm dev'. The approach limits casual discovery of secrets in readable files but, the developer cautions, does not protect against an agent that can run the op CLI, access the vault, or inspect a process that received the resolved values.

by read7 min views1 publishedNov 13, 2026

If a coding agent can read your project files, assume it can read your .env too.

Ignore rules and editor settings can help, but they are not a security boundary. I moved secret values out of my project files and into 1Password, then used the CLI to provide them to the processes that need them.

That reduces one easy way for an agent to discover secrets. It does not make secrets safe from code the agent writes or commands it runs. I’ll cover that part too.

Before, my project had a file containing actual values:

STRIPE_API_KEY=replace-with-your-key
SENTRY_TOKEN=replace-with-your-token
API_URL=http://localhost:8787

Now, the shared secrets live in 1Password. The project contains references to them instead:

STRIPE_API_KEY=op://My-Project/api-env/STRIPE_API_KEY
SENTRY_TOKEN=op://My-Project/api-env/SENTRY_TOKEN

Then I start the app with:

op run --env-file=op.env -- pnpm dev

op run resolves the references and provides the values to the process it starts. It does not, by itself, write those resolved values to a file.

An agent that reads op.env sees references, not secret values. But if it can run op, access the vault, or inspect a process that received the secrets, that protection may not be enough.

Not every environment variable is a secret. Go through your existing files one value at a time:

op.env..env.local. For example:

File Contents Git
.env.local Non-sensitive, machine-specific settings Ignored
op.env References to shared secrets Committed

Make sure .env.local is actually ignored. Add it to .gitignore if it isn’t already:

.env.local

The op:// references reveal metadata such as vault, item, and field names, so use names you’re comfortable exposing in the repository. Don’t point development references at a vault containing production credentials.

The desktop app and CLI are separate installations. Follow 1Password’s CLI installation guide for your platform.

brew install --cask 1password-cli
winget install AgileBits.1Password.CLI

In the 1Password desktop app, enable Settings → Developer → Integrate with 1Password CLI. Then open a new terminal and try:

op vault list

Authenticate when prompted, and check that you can see the vault you intend to use. Keep the development vault scoped to development credentials.

Do this yourself, in a terminal or the 1Password app—not through the coding agent. If the agent reads the old file while you migrate it, the secret has already entered the environment you’re trying to protect.

Create an item in 1Password and add each secret as a concealed field. Avoid passing secret values as command-line arguments: depending on the system and tooling, arguments can be exposed through process listings or monitoring.

Then create op.env with one reference per secret. For example:

STRIPE_API_KEY=op://My-Project/api-env/STRIPE_API_KEY
SENTRY_TOKEN=op://My-Project/api-env/SENTRY_TOKEN

Keep the file format simple: one NAME=op://... reference per line. This check flags any non-comment, non-blank line that doesn’t match that format:

grep -nEv '^(#|[A-Za-z_][A-Za-z0-9_]*=op://|$)' op.env

No output means every line matches the expected shape. It does not prove the references point to the right fields, or that a secret wasn’t committed elsewhere.

Check the diff before committing, and rotate any credentials an agent may already have seen. Moving a credential into a vault does not undo an earlier exposure.

op run For most apps, start the process that needs the secrets through 1Password:

op run --env-file=op.env -- pnpm dev

The secret values are now available to the app and its child processes. They are no longer just references—but they are still accessible to code running in that process.

Give each service only the secrets it needs. If you run multiple services, use separate references or vault items rather than handing every service the same broad set of credentials.

Wrangler’s local variable-file behavior matters here. If .dev.vars exists, Wrangler may not use the process environment the way you expect. Wrangler 4.27 and later support .env.local; CLOUDFLARE_INCLUDE_PROCESS_ENV=true enables merging the process environment as well. Check the Wrangler environment variable documentation for the behavior in the version you use.

If you currently use .dev.vars:

.dev.vars. Bash or zsh:

if [ -f op.env ]; then
  CLOUDFLARE_INCLUDE_PROCESS_ENV=true \
    op run --env-file=op.env -- wrangler dev
else
  wrangler dev
fi

PowerShell:

if (Test-Path op.env) {
  $previous = $env:CLOUDFLARE_INCLUDE_PROCESS_ENV
  try {
    $env:CLOUDFLARE_INCLUDE_PROCESS_ENV = 'true'
    op run --env-file=op.env -- wrangler dev
  } finally {
    $env:CLOUDFLARE_INCLUDE_PROCESS_ENV = $previous
  }
} else {
  wrangler dev
}

The process-environment setting can expose more of the environment than you intended to the Worker. Set it only for the command that needs it, and test the behavior with your Wrangler version.

Avoid using op inject to write resolved secrets into .dev.vars or another project file. That puts plaintext back on disk.

For CI, use a 1Password service account with read-only access to the specific vault it needs. Store its token as a GitHub Actions secret on a protected environment, not as a broadly available repository secret.

This example loads secrets as step outputs rather than exporting them into the whole job environment:

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4

      - name: Load secrets from 1Password
        id: op
        uses: 1password/load-secrets-action@v5
        with:
          export-env: false
        env:
          OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
          CLOUDFLARE_API_TOKEN: op://My-Project/ci/CLOUDFLARE_API_TOKEN
          STRIPE_API_KEY: op://My-Project/api-env/STRIPE_API_KEY

      - name: Deploy Worker
        uses: cloudflare/wrangler-action@v4
        env:
          STRIPE_API_KEY: ${{ steps.op.outputs.STRIPE_API_KEY }}
        with:
          apiToken: ${{ steps.op.outputs.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
          workingDirectory: workers/api
          secrets: |
            STRIPE_API_KEY

The secrets input names the variables Wrangler should upload; the values come from the step’s environment. Keep the service-account token and loaded values away from steps that do not need them.

Before using this, check the actions’ current documentation. For stronger supply-chain protection, pin actions to reviewed commit SHAs rather than relying only on version tags. Never make secrets available to workflows running untrusted code, such as pull requests from forks.

A vault keeps secret values out of files. It does not keep them out of processes.

When op run starts your app, the app receives ordinary environment variables. Code in that process can read them. A malicious dependency or a change the agent made could send them over the network.

Other processes running as your user may also be able to inspect process environments. For example, macOS has ps eww <pid> and Linux exposes process environment information under /proc/<pid>/environ, subject to system permissions and configuration.

And if you start the agent from a shell that already has secrets exported, commands it runs may inherit those values.

What helps:

A command allowlist is not a complete defense. An allowed command such as pnpm test or node can execute code in the project.

Agent settings can reduce accidental access, but they are not a replacement for keeping plaintext secrets out of the workspace.

You can add deny rules for secret files and the 1Password CLI in Claude Code’s settings. Check the current Claude Code permissions documentation for the supported syntax and behavior.

Organizations on Copilot Business or Enterprise can configure content exclusions. These can limit what Copilot accesses, but GitHub documents limitations for indirect access, such as a script reading an excluded file.

VS Code also provides settings for edit approval, terminal approval, and agent sandboxing. These settings vary by version and agent mode, so verify them against the current VS Code documentation.

A sandbox can restrict an agent’s commands, filesystem access, and network access. It does not necessarily protect a secret file that remains readable inside the workspace. And disabling inline suggestions for .env files is not the same as preventing an agent from reading them.

Keep secret values out of files the agent can read. Use runtime injection to provide credentials only to the process that needs them, and assume that process can access those credentials.

The vault prompt is useful for protecting vault access. If you get an unexpected prompt, deny it. But a prompt cannot protect secrets already handed to a running process.

This setup reduces exposure; it does not eliminate it. Use narrow, disposable credentials, and review what the agent changed before you run it.

Commands and settings can change. Check the current 1Password CLI, Wrangler, GitHub Actions, and editor documentation before adopting them.

── more in #ai-agents 4 stories · sorted by recency
── more on @1password 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/your-coding-agent-ca…] indexed:0 read:7min 2026-11-13 · —