The 3.2% Secret-Leak Rate Hiding in AI-Assisted Commits
AI-assisted commits leak credentials at roughly double the baseline GitHub rate. The mechanism isn't a smarter attacker — it's a faster typist with no memory of what it just wrote.
Somewhere in your git history, there's a good chance a real credential is sitting in a commit that looked completely unremarkable at the time. Across all public GitHub commits, the baseline rate of secret leaks — API keys, tokens, database passwords committed in plaintext — sits around 1.5%. Among AI-assisted commits, that rate is 3.2%. Not a marginal bump. Roughly double.
That number deserves more attention than it gets, because most conversations about AI coding risk jump straight to exotic vulnerabilities — injection attacks, auth bypasses, logic flaws that require real expertise to introduce or spot. A leaked credential requires none of that sophistication to cause damage. It's the simplest possible failure: a string that should have stayed secret didn't, and now it's indexed, cached, and searchable by anyone who knows to look. The doubling in AI-assisted commits isn't because the model is worse at security than a human — it's because the model has no concept of "secret" at all, only of "plausible code."
Why the model leaks what a human wouldn't
A developer writing a database connection by hand almost always pauses at the password. There's a moment — brief, often subconscious — where you register "this is the real one" and either pull it into an environment variable or, worse, know you shouldn't but do it anyway under deadline pressure. Either way, a human touches that value and has some chance of recognizing what it is.
A model generating the same connection code has no equivalent moment. It's pattern-completing based on what connection strings and config blocks typically look like in the codebase it can see — and if it can see a real key in a .env file, a config comment, a previous commit, or an open tab's context, it will often reproduce that value verbatim because reproducing what's around it is exactly what a language model does well. It's not "deciding" to leak a secret. It's completing a pattern that happens to contain one, with no separate faculty that would flag "this specific token deserves different handling than the rest of the code around it."
The volume multiplier makes it worse
This compounds with a second, more mundane factor: AI-assisted developers simply generate more commits, more files, more scaffolding in the same amount of time. If leak rate held steady per line of code, more lines would still mean more absolute leaks. But it doesn't hold steady — it rises — which means both factors point the same direction at once. More generated code, and a higher proportion of that code carrying an exposed credential.
Put those together and you get a specific, unglamorous failure pattern: a developer asks for a working example — a script to hit an internal API, a test fixture, a quick integration — the model produces something that runs on the first try because it's using a real value it picked up from context, and the commit goes through because it worked. Nobody was being careless in the way "careless" usually gets described. The code passed its own bar: it ran.
Why this is worse than it sounds
A leaked credential isn't a slow-burn architectural problem you can schedule a refactor around. It's live the moment it's pushed. Public repos get scanned continuously — by GitHub's own secret-scanning partners, by security researchers, and by automated bots that do nothing but crawl new commits for exactly this pattern. The gap between "credential lands in a public commit" and "credential gets used by someone who isn't you" is frequently measured in minutes, not days. Even private repos aren't safe by default — a repo that goes public later, a fork, a CI log that echoes an env var, a screen-shared terminal, any of these turn a private leak into a public one instantly and after the fact, when nobody's watching for it anymore.
And because the leak often lives inside otherwise-correct, working code, it doesn't announce itself the way a bug does. A broken feature gets reported. A leaked credential just sits there working exactly as intended — for whoever finds it.
What actually catches this
The fix isn't "read every line the model generates hunting for secrets" — that's the kind of advice that sounds responsible and gets ignored under real deadline pressure, which is precisely the condition under which these leaks happen in the first place. What catches this reliably is automation that doesn't get tired or rushed:
- Pre-commit secret scanning (gitleaks, truffleHog, or your git host's native scanning) run as a hook, not a CI step that runs after the push already happened. The whole point is catching it before it's public.
- Environment-variable-only policies enforced by linting, not convention — a lint rule that fails the build on any string matching common key formats (
sk-,AKIA, JWT structure, etc.) in a non-config file. - Short-lived credentials wherever the platform supports them, so that a leaked value has a small blast radius by default instead of relying on humans to rotate it fast enough after the fact.
- A repo-wide audit for existing exposure, not just new-commit scanning — because the 3.2% rate applies to commits already sitting in your history, not just the ones you write tomorrow.
None of this requires distrusting AI-assisted development or slowing it down meaningfully. It requires treating secret exposure as a category that gets automated defense by default, the same way most teams already automate dependency vulnerability scanning without thinking twice about it.
Why this hits small teams harder than it looks
Large organizations often have security tooling procured years ago, baked into onboarding, running whether anyone thinks about it or not. Solo builders and small teams frequently don't — secret scanning gets added, if it gets added at all, after a scare, not before one. That's a dangerous ordering given how fast a leaked credential can be exploited once it's public. A five-person team shipping fast with AI assistance is generating commits at a rate that would have taken a much larger team to produce a few years ago, without necessarily having the tooling maturity that larger team would have accumulated.
There's also a specific small-team pattern worth naming: the "just get it working, clean it up later" instinct that's especially strong on a lean team with no dedicated ops or security hire. A working integration with a hardcoded key checked in "temporarily" is a completely normal thing to do under deadline pressure — and it's also exactly the moment a 3.2%-rate event happens, because "temporarily" doesn't change what a public commit does the instant it's pushed. The credential doesn't know it was meant to be swapped out next week.
The rotation habit nobody budgets time for
Scanning catches the leak. It doesn't undo the exposure. Once a secret has been pushed publicly — even briefly, even if deleted in a follow-up commit — the only safe assumption is that it's compromised, because git history doesn't forget, and force-pushing a fix doesn't reliably scrub every cache, fork, or mirror that might have already pulled it. This means the actual remediation step isn't "remove the string from the file." It's "rotate the credential," which is a different, often-skipped action because it requires touching whatever system issued the credential in the first place, not just the repository.
Teams that handle this well build credential rotation into their incident response as a reflex, not a judgment call — any flagged secret gets rotated immediately, regardless of how confident anyone feels that "nobody probably saw it." That confidence is exactly the thing the automated scanners on the other side of this equation don't share, and they're scanning continuously, at a speed no human confidence-check can outrun.
The pattern behind the pattern
This is the first of several places in this series where the same shape repeats: AI code generation doesn't introduce a new kind of failure, it removes a friction that used to catch an old one. Credential leaks existed long before language models wrote code. What's changed is the rate, and the rate changed because the moment where a human used to notice — the pause before committing something that looks like a real secret — got automated away along with everything else.
A model that writes fluent, working code by pattern-matching what's around it will pattern-match your secrets with exactly the same confidence it pattern-matches your syntax. It has no separate alarm for the thing that matters most.
The fix isn't asking developers to slow down and look harder — that's a strategy that degrades under pressure, and pressure is when this happens. The fix is a scanning layer that doesn't care about deadlines at all.
Part of the "From Vibe Coding to Production" series on aiskill.market.
Related Skills to Try
Related Skills to Try
API credentials hygiene
Audits and hardens API credential handling (env vars, separation, rotation plan, least privilege, auditability). Use when integrating services or preparing production deployments where secrets must be
Claude Code Mastery
Master Claude Code for coding tasks. Includes setup scripts, dev team subagents (starter pack or full team), self-improving learning system, diagnostics, and troubleshooting.