AI agents commit secrets 2x more oftenThe mechanism. The four failure modes. The fix.
GitGuardian's State of Secrets Sprawl 2026 put a number on what security teams already suspected: AI-assisted commits leak secrets at roughly twice the rate of human-only commits. AI-service token leaks jumped 81% year-over-year.
-
01
Cause
No secret/config distinction
Agent context window absorbs env vars, keys, and config as plain text
full env at session start -
02
Mechanism
Secrets land in commits
Autocomplete, state files, and auto-push put values into git history
2x baseline leak rate -
03
Outcome
AI-service token spike
GitGuardian 2026: +81% YoY in AI-service token exposures
81% YoY increase
TL;DR· the answer, in twenty seconds
What: AI coding agents inherit your full shell environment and have no built-in way to distinguish a secret from ordinary config. GitGuardian's State of Secrets Sprawl 2026 found AI-assisted commits leak secrets at roughly twice the rate of human-only commits, with AI-service token leaks up 81% year-over-year.
Fix: wrap every agent session with hasp run -- claude (or equivalent process-scoped injection) so the agent receives only the credentials the current task needs, not your entire shell environment. Add hasp check-repo as a pre-push hook to catch anything that slipped through.
Lesson: the problem is architectural, not behavioral. Agents read ambient state. Stop putting secrets in ambient state.
GitGuardian published State of Secrets Sprawl 2026 in late February. The headline number got attention: AI-service token leaks up 81% year-over-year. The more durable finding sat in a footnote-sized data point buried in the methodology section: AI-assisted commits leak secrets at roughly twice the rate of commits written without AI assistance.
That ratio matters more than the 81% spike. Token categories come and go. The 2x leak multiplier points at something structural in how coding agents handle credentials.
The structure is simple. Agents inherit your full environment. They have no runtime concept of "this value is a secret, do not put it in code." They write state files to disk, suggest completions based on what they see in context, and in agentic workflows they commit and push without a human reviewing each diff. The multiplier is a predictable outcome of those four properties interacting.
This article unpacks each failure mode with a reproducible example. The GitGuardian report does not name specific agents. All four modes apply to Claude Code, Codex, Cursor, and Aider equally. Use whatever you use; the plumbing is the same.
What to know in 60 seconds
- GitGuardian's State of Secrets Sprawl 2026 found AI-assisted commits expose secrets at ~2x the rate of human-only commits.
- AI-service token leaks (OpenAI keys, Anthropic keys, etc.) jumped 81% year-over-year in the same report.
- Agents do not distinguish secrets from config at runtime. They read whatever your shell exports.
- Four concrete mechanisms drive the leak rate: ambient env absorption, autocomplete context bleed, pre-commit hook bypass, and gitignore blindness.
- The fix is process-scoped secret injection, not better agent prompting.
Failure mode 1: the agent reads your entire environment
When you launch Claude Code or any terminal-based agent, the child process inherits os.environ from your shell. That means every variable you have exported, globally or per-project, is readable inside the agent's execution context from the first token.
Run this in a shell where you have any secrets loaded:
export STRIPE_SECRET_KEY=sk_live_abc123
claude code "what environment variables do you see?"
The agent will enumerate them. It has to. It reads os.environ to understand paths, proxy settings, language configs, and tool locations. There is no mechanism inside the agent runtime that says "ignore values that look like bearer tokens." It sees everything, and it can write what it sees into any file it generates.
If you run the agent through a broker like hasp instead, the shell export does not happen. The agent's process starts with a clean env, hasp injects the credential at the specific call site that needs it, and the value vanishes when that process exits. State files the agent writes hold references. The autocomplete context window never sees a live key to pattern-match against.
The Knostic disclosure from February 2026 demonstrated this with Claude Code's settings.local.json. The file captured live env vars from the agent session and wrote them to a predictable on-disk path. That was not an exploit of Claude's language model. It was a standard child-process environment inheritance, persisted.
Codex and Cursor have analogous state files. Different names, same shape.
Failure mode 2: autocomplete pulls secrets into source files
Code completion models train on code that contains secrets. They also use your open buffers and recent context to generate suggestions. Both effects push credential values toward the cursor.
Concrete example. You have a test file:
# tests/test_payments.py
import os
STRIPE_KEY = os.environ.get("STRIPE_SECRET_KEY") # loaded from env
You ask the agent to scaffold a new integration test. It reads the existing test file as context, sees the pattern, and suggests:
STRIPE_KEY = "sk_live_abc123" # hardcoded from context
Claude Code and Copilot both exhibit this when the live value is visible in the session context. The model pattern-matches against what it has seen. You review the diff quickly because it looks right. You commit.
This failure mode requires no agent state file and no special behavior. Standard completion. Standard context window. Standard commit.
The GitGuardian Labs 2026 report cites this as a contributing factor to the 2x multiplier, describing it as "AI-assisted developers accepting completions that contain values sourced from session context." Developers review AI-generated code at a faster pace than code they wrote themselves. Speed plus ambient context equals leaked values.
Failure mode 3: agentic workflows skip the human review step
Claude Code in agentic mode, configured with allow_bash and auto-commit enabled, can run git add -A && git commit -m "..." && git push without prompting. This is the intended behavior for autonomous tasks. It is also how secrets reach a remote in minutes.
The sequence:
# developer starts a long-running agent task
claude code "refactor the payment module and push when done"
The agent generates code, some of which references values it saw in the env or in existing files. It stages everything under the project root. git add -A picks up .env, config/secrets.json, or any file that was not gitignored but holds credential data. It commits. It pushes.
No pre-commit hook ran. In most agentic configurations, hooks are either disabled for speed or bypass-flagged with --no-verify because the hook prompts interactively and the agent cannot respond. The agent does not run gitleaks or trufflesecurity/detect-secrets before committing. It treats git add -A as a packaging step.
The push lands on the remote before you see the summary. If the repo is public, bots scrape new commits in under two minutes. If it is private, the secret is still in history, which is now on GitHub, GitLab, or Bitbucket's servers.
This failure mode is the highest-severity one from the GitGuardian data. Automated commits with no human gate apply no judgment at the staging step. The entire credential hygiene burden falls on gitignore correctness and gitleaks not being in the loop.
Failure mode 4: the agent does not know your gitignore coverage is incomplete
Gitignore files are incomplete. Always. Most .gitignore templates shipped before coding agents existed. They do not cover .claude/, .cursor/, .aider/, .codex/, or any of the state directories these tools create by default.
An agent running in a repo with a standard Node.js .gitignore will not know that .claude/settings.local.json is untracked but not ignored. It will not check. It will not warn you. When you or the agent run git add -A, that file enters the index.
Same problem with .env.local, config/credentials.yml.enc (when the key is checked in alongside it), and any tool-specific config file created after the ignore template was written.
The agent does not interrogate gitignore coverage before touching the filesystem. It writes what the task requires and assumes the existing gitignore is correct. This assumption fails for every new tool that creates a new directory.
A minimal audit you can run right now:
# list tracked files that look like they should not be tracked
git ls-files | grep -E '\.env|secret|credential|token|api.key|\.claude|\.cursor|\.aider'
If that returns anything, you already have the problem. The agent did not cause it. The missing gitignore entry did. The agent just committed it without noticing.
What gets missed in the 81% statistic
The 81% YoY spike in AI-service token leaks from GitGuardian is real and worth citing. What it does not tell you is the breakdown by mechanism.
Most coverage of the stat treats it as a story about developers being careless with AI API keys. That framing is wrong. The 81% does not mean developers are putting their OpenAI keys into prompts. It means AI-service tokens are the credential category that grew fastest, because more developers are now using these services, storing the tokens in their environments, and working in workflows where those environments bleed into commits via the four mechanisms above.
The leak rate is a supply problem before it is a behavior problem. More tokens in more environments, more agents reading those environments, more automated commits without human review. The number goes up even if individual developer behavior stays constant.
The 2x multiplier is cleaner evidence of structural risk. It controls for the supply increase. Even accounting for more secrets in more repos, AI-assisted commits expose them at twice the rate. The mechanism is the diff.
GitGuardian's methodology for the 2x figure distinguishes commits where AI assistance was detectable (Copilot signature, agent commit messages, commit metadata from known agent flows) from baseline commits in the same repos. The 2x holds across languages and organization sizes, per the 2026 report.
A pasteable checklist for your next PR
## AI-agent secret hygiene checklist
- [ ] .claude/, .cursor/, .aider/, .codex/ in .gitignore
- [ ] Same paths in .npmignore / MANIFEST.in / .dockerignore (if shipping packages)
- [ ] git ls-files | grep -E '.env|secret|credential|token|\.claude|\.cursor' returns nothing
- [ ] gitleaks or detect-secrets runs in CI (not just pre-commit)
- [ ] Pre-push hook that scans staged content for known-bad patterns
- [ ] Agent auto-commit disabled, or commit step requires human approval
- [ ] --no-verify flag absent from any agent-driven git commands
- [ ] Secrets loaded into agent sessions via process-scoped injection, not shell export
- [ ] Audit log reviewed after any agentic task that touched files with credentials
- [ ] Rotated any credential that was in env during agent sessions touching public repos
Drop this into your repo's SECURITY.md or a PR template. It applies to any agent, not just Claude Code.
What this means for your stack
The four failure modes above share a root. Secrets live as long-lived ambient environment variables. Agents read everything in that environment. Some fraction of what they read ends up in files, completions, or commits. That fraction grows when the agent runs autonomously.
The architectural fix is process-scoped injection: a local broker holds credentials in an encrypted vault, the agent requests access per-task, the broker injects values into a specific child process at exec time, and the values vanish when that process exits. The agent context window holds a reference, not the secret. State files the agent writes hold references too. Gitignore coverage gaps stop mattering for secrets that were never in the filesystem.
hasp is one working implementation. curl -fsSL https://gethasp.com/install.sh | sh, hasp setup, connect a project, then wrap agent sessions with hasp run -- claude. Run hasp check-repo before any push. Source-available (FCL-1.0), local-first, macOS and Linux, no account.
The 2x leak multiplier will not drop from better agent prompting or from adding more .gitignore entries. It drops when secrets stop living in the place agents read from.
Sources· cited above, in one place
Stop handing the agent your real keys.
hasp keeps secrets in one local encrypted vault, brokers them into the child process at exec, and never lets the agent read the value.
- Local, encrypted vault — no account, no cloud, no telemetry by default.
- Brokered run — agent gets a reference, the child process gets the value.
- Pre-commit + pre-push hooks catch managed values before they ship.
- Append-only HMAC audit log answers "did the agent touch the prod token?" in seconds.
macOS & Linux. Source-available (FCL-1.0, converts to Apache 2.0). No account.