
Productivity · Guide
How to Stop AI Coding Agents Leaking Secrets
A layered guide to keeping API keys away from Claude Code, Codex CLI and Cursor: deny rules, sandboxes, env filtering, pre-commit hooks, push protection and expiring tokens.
Wajid Ali · Oct 28, 2026 · 11 min read
On this page
AI coding agents leak secrets in three ways: they read them from your files and environment, they print them into a transcript or log, and they commit or push them. You stop that with layers, not one setting: keep credentials out of the agent's reach, sandbox what its shell can read and send, block secrets at commit and push time, and make any token that still escapes short-lived. This guide walks through each layer for Claude Code, Codex CLI, Cursor and GitHub, using only what the vendors document today.

Image: GitHub Changelog, GitHub CLI: Opt in to expiring, auto-refreshing OAuth tokens, October 21, 2026.
Why agents are a new secret-leak path
A human developer who opens .env knows not to paste it into a chat. An agent doesn't have that instinct. It reads whatever helps it finish the task, runs commands whose output lands in its context window, and can commit a file the moment it decides the file belongs in the repo. Every one of those steps can move a credential somewhere it shouldn't be: the model provider's logs, a shared session transcript, a pull request, or a public repository.
There's also a newer problem: instructions you didn't write. When we covered how an AGENTS.md dropped into Downloads could hijack a coding agent, the payload talked the agent into editing its own config and running with its sandbox switched off. An agent that can read your keys and reach the network can be steered into sending them somewhere. So the goal isn't only "don't commit secrets." It's "limit what the agent can see, limit where it can send things, and catch what slips through."
Think of it as four layers:
- Reach: what files and environment variables the agent can read at all.
- Egress: where its commands can send data.
- Commit and push: scanners that block a secret before it lands in Git history.
- Blast radius: credentials that expire quickly or are scoped so narrowly that a leak matters less.
Layer 1: Keep secrets out of the agent's reach
The cheapest leak to prevent is the one where the agent never sees the secret. Start with files, then environment variables.
Claude Code: deny Read rules
Claude Code's settings documentation shows permission rules in settings.json that stop it reading .env files. A minimal version, adapted from the documented example:
{ "permissions": { "deny": [ "Read(./.env)", "Read(./.env.*)", "Read(./secrets/**)" ] }}
Know the limits before you rely on it. The permissions docs say Read and Edit deny rules apply to Claude's built-in file tools and to file commands it recognizes in Bash, such as cat, head, tail, sed and tee, plus redirect targets. They don't apply to a command that reads files without naming them, like a recursive grep, or to a Python or Node script that opens files itself. Anthropic's own advice is to enable the sandbox when you need OS-level enforcement. The same page also notes that a .claudeignore file has no effect; move those entries into Read deny rules.
Cursor: .cursorignore, and its gap
Cursor's ignore file docs say a .cursorignore file in your project root blocks listed files from the Agent, Tab and @-mention references. It also supports a global ignore list in user settings, which is empty by default; the docs suggest patterns like **/.env, **/.env.*, **/credentials.json and **/secrets.json.
The important caveat is spelled out on the same page: the terminal and MCP server tools used by Agent cannot block access to files governed by .cursorignore. If the agent runs cat .env in the terminal, the ignore file doesn't stop it. Treat .cursorignore as a context filter, not a security boundary, and keep real credentials out of the project folder.
Codex CLI: strip secret-looking environment variables
Environment variables are the leak people forget. Codex's config reference documents a shell_environment_policy block that controls what the agent's subprocesses inherit. One setting matters here: ignore_default_excludes. Per the docs, it defaults to true, which keeps variables whose names contain KEY, SECRET or TOKEN. Set it to false and Codex applies its automatic secret-name exclusions instead. An illustrative ~/.codex/config.toml snippet:
[shell_environment_policy]inherit = "core"ignore_default_excludes = false
inherit accepts all, core or none as the baseline, and set lets you inject only the specific values a task needs. Name-based filtering won't catch a variable called DB_URL with a password embedded in it, so pair this with a short allowlist rather than trusting the defaults.
Codex 0.164 also started masking credentials in supported remote Bash and Zsh snapshot sessions. That helps with what ends up in the transcript, but the release notes scope it to those session types. It's a second line, not the first.
The rule that works everywhere
Don't keep long-lived production credentials in the folder you point an agent at. Use a development key with tight limits, load secrets from a manager at run time rather than a checked-out .env, and never start an agent in your home directory or Downloads.
Layer 2: Sandbox what the agent's shell can read and send
Reach controls are about files the agent's tools open directly. A sandbox is the OS-level backstop for everything its shell runs.
Codex CLI
OpenAI's Codex security page says the CLI and IDE extension enforce sandbox policies with OS-level mechanisms, and that the defaults are no network access and writes limited to the active workspace. That default is the single biggest protection against exfiltration: a command that can't reach the internet can't post your key to a paste site. Be deliberate before you turn network access on, and treat --dangerously-bypass-approvals-and-sandbox as exactly what its name says. That flag is what the Downloads-folder attack got the agent to use.
The same page shows how to keep stricter approvals for a sensitive project: add a [projects."/path/to/project"] entry with trust_level = "untrusted" to your user-level ~/.codex/config.toml, and commands then require approval.
Claude Code
Claude Code's sandboxing docs are unusually candid about the defaults. With the sandbox on, shell commands can write only to the working directory, a per-user temp directory and directories you've added. Network traffic has no direct route out; it goes through a local proxy that checks each host against your allowed domains. But reads cover most of the machine by default, including credential files such as ~/.ssh and ~/.aws/credentials, and commands inherit Claude Code's environment, including any secrets in it.
So turning the sandbox on is step one, and telling it what to protect is step two. The docs show a sandbox.credentials block that denies sandboxed commands access to specific files and environment variables:
{ "sandbox": { "enabled": true, "credentials": { "files": [ { "path": "~/.aws/credentials", "mode": "deny" }, { "path": "~/.ssh", "mode": "deny" } ], "envVars": [ { "name": "GITHUB_TOKEN", "mode": "deny" }, { "name": "NPM_TOKEN", "mode": "deny" } ] } }}
Entries also accept a mask mode: sandboxed commands see a per-session placeholder, and the sandbox proxy substitutes the real value only on outbound requests to hosts you allow. That's the right shape for an API key the agent genuinely needs to call one service. Two more details from the docs are worth knowing. The sandbox wraps shell commands, so built-in file and web tools run outside it and still need permission rules. And CLAUDE_CODE_SUBPROCESS_ENV_SCRUB strips credentials from all subprocesses regardless of sandboxing.
On Linux and WSL2 the sandbox depends on bubblewrap and socat; run /sandbox in a session to see whether anything is missing.
Layer 3: Block secrets at commit and push
Assume something will slip past layers one and two. The next chance to stop it is before it enters Git history, because once a secret is pushed, deleting the file doesn't remove it from history.
A local pre-commit hook
Gitleaks is an open-source, MIT-licensed scanner that its README says can run as a pre-commit hook or as a GitHub Action. With the pre-commit framework installed, a .pre-commit-config.yaml at the repo root looks like this (illustrative; pin the current release, v8.30.1 at the time of writing):
repos: - repo: https://github.com/gitleaks/gitleaks rev: v8.30.1 hooks: - id: gitleaks
Then run pre-commit install. A hook helps most when the agent commits for you, because the agent hits the same failure a human would and has to fix it. Hooks only run where they're installed, though, so this is a convenience layer, not an enforcement point. To check what an agent already committed on a branch, gitleaks git -v scans history.
GitHub push protection
The server side is where enforcement lives. GitHub's push protection docs say it blocks detected secrets in command-line pushes, commits made in the GitHub UI, file uploads, REST API requests, and interactions with the GitHub MCP server on public repositories. Push protection for users is on by default and stops you pushing secrets to public repositories on github.com. For private repositories you need repository-level push protection, which comes with GitHub Secret Protection.
Two details matter for agent workflows. First, by default anyone with write access can bypass a push protection block by giving a reason; GitHub creates an alert when they do, and delegated bypass can restrict who's allowed. An agent with write access and a persuasive prompt is "anyone with write access," so consider delegated bypass on repos agents push to. Second, GitHub says the MCP-specific protection is on by default for MCP interactions with public repositories, and with private repositories covered by GitHub Advanced Security, whether or not push protection is enabled in the repo's settings. It blocks secrets in AI-generated responses and in actions like creating an issue.
Let the agent scan itself
GitHub also lets an agent run secret scanning before it commits, through the remote GitHub MCP server. Per GitHub's guide, it needs Secret Protection on the repo, the secret_protection toolset (not in the default set), and the run_secret_scanning tool added explicitly. It works in MCP clients including Claude Code and Cursor, but not with a local MCP server configuration. The findings are ephemeral: they show up in the agent's chat for that session and don't become alerts, so GitHub itself calls it a pre-commit check, not a system of record.
GitHub's partner program also adds detectors for the keys AI app builders generate, as when secret scanning added Lovable and Supabase keys.
Layer 4: Shrink the blast radius
Some leaks will get through every filter. The remaining question is how long a leaked credential works and what it can do.
- Expiring CLI tokens. GitHub CLI v2.103.0 added opt-in expiring OAuth tokens in public preview, per the GitHub changelog. Log in with
gh auth login --expiring, or rungh config set expiring_credentials enabledto make it the default. GitHub says a leaked access token then becomes unusable within hours instead of lasting indefinitely. If you use git over HTTPS, GitHub recommendsgh auth setup-gitso gh serves and refreshes the credential. - Apps instead of personal tokens. For automation, a GitHub App gets its own identity, per-permission scopes and short-lived installation tokens. Enterprise installations went GA in October, which removes a common reason to hand an agent a classic PAT; see GitHub Apps can now replace enterprise PATs.
- OIDC in CI. If an agent edits your workflows, prefer cloud credentials issued through GitHub Actions OpenID Connect over long-lived cloud keys stored as repository secrets.
- Leaks outside your repos. Enterprises on GitHub Enterprise Cloud can catch credentials their people leak in other public repositories; public monitoring now has an API and webhooks so those alerts can feed your incident pipeline.
A 30-minute checklist
If you only do one pass this week, do this, in order:
- Move production credentials out of any folder an agent works in, and give agents development keys with spending or scope limits.
- Add
.envand credential deny rules: Read deny rules in Claude Code, a global ignore list in Cursor. - In Codex, set
ignore_default_excludes = falseand a narrowinheritbaseline undershell_environment_policy. - Keep Codex's network-off default, and enable the Claude Code sandbox with
credentialsdeny or mask entries for your keys. - Install a Gitleaks pre-commit hook in repos agents commit to.
- Turn on push protection for private repos, and consider delegated bypass where agents have write access.
- Switch gh to expiring tokens and replace classic PATs used by automation with GitHub Apps.
Verdict
No single vendor setting stops AI coding agents leaking secrets, and several of the popular ones are weaker than they look: Cursor's .cursorignore doesn't cover the terminal, and Claude Code's Read rules don't cover a script that opens files itself. The controls that actually hold are the OS-level ones (Codex's network-off sandbox, Claude Code's sandbox with credential deny or mask entries) plus server-side push protection. Start there, add a pre-commit hook for faster feedback, and make every token the agent can touch expire on its own. If you run agents on a team, the highest-value single change is keeping production credentials out of agent working directories entirely.
Sources
- Anthropic, Claude Code settings, accessed Oct 28, 2026.
- Anthropic, Claude Code permissions, accessed Oct 28, 2026.
- Anthropic, Claude Code sandboxing, accessed Oct 28, 2026.
- OpenAI, Codex agent approvals and security, accessed Oct 28, 2026.
- OpenAI, Codex config reference, accessed Oct 28, 2026.
- OpenAI, Codex CLI rust-v0.164.0 release notes, Oct 23, 2026.
- Cursor, Ignore file, accessed Oct 28, 2026.
- GitHub Docs, About push protection, accessed Oct 28, 2026.
- GitHub Docs, Push protection and the GitHub MCP server, accessed Oct 28, 2026.
- GitHub Docs, Scanning for secrets with the GitHub MCP server, accessed Oct 28, 2026.
- GitHub Changelog, GitHub CLI: Opt in to expiring, auto-refreshing OAuth tokens, Oct 21, 2026.
- Gitleaks, gitleaks/gitleaks README, accessed Oct 28, 2026.
Frequently asked questions
- Can AI coding agents read my .env file?
- Yes, by default most agents can read any file in the folder you start them in. Claude Code supports Read deny rules for .env files, Cursor supports .cursorignore, and Codex can filter environment variables, but each has documented gaps, so keep production credentials out of agent working directories.
- Does .cursorignore stop Cursor's agent from reading secrets?
- Only partly. Cursor's docs say .cursorignore blocks files from Agent, Tab and @-mentions, but the terminal and MCP server tools used by Agent cannot block access to those files. Treat it as a context filter, not a security boundary.
- Does GitHub push protection block secrets pushed by AI agents?
- Yes. Push protection blocks detected secrets in command-line pushes, UI commits, uploads, REST API requests and GitHub MCP server interactions on public repositories. For private repositories you need GitHub Secret Protection with push protection enabled, and anyone with write access can bypass by default unless you set up delegated bypass.
- What should I do if an AI agent committed a secret?
- Revoke or rotate the credential first, because deleting the file does not remove it from Git history. Then scan the branch history, for example with gitleaks git, and rewrite history only after the key is already dead.