The telling number in the latest Shai-Hulud news is not 469. It is 189, the number of credential paths earlier variants checked, because the gap between the two means the worm's authors audited their own coverage and found 280 places on a developer machine they had been skipping. Attackers iterate on their steal lists the way your team iterates on a roadmap. That should bother you more than the headline figure.
On September 3, The Hacker News published GitGuardian's account of the finding: in early August, its researchers caught a recent variant of the Shai-Hulud infostealer worm scanning 469 credential locations spanning developer environments, CI/CD tooling, cloud configurations, and AI tool configs. Within a day the story was syndicated across a string of security news sites, every one of them repeating the same two numbers and the same framing. None answered the only question a defender actually has: which 469?
The list nobody published
GitGuardian's writeup names the categories but never enumerates the paths. The examples given are .env files, shell history, package-manager configuration, CLI caches, CI/CD configurations, IDE settings, and configuration used by AI development tools. That is seven shelves in a very large cabinet, and the cabinet itself stays closed.
So I will do the enumeration the coverage skipped. The reconstruction below comes from the named categories plus one premise: credential files on developer machines are boringly predictable, because tools write them to the same default paths on every laptop on earth. If GitGuardian's list differs from mine at the margins, your defensive work does not change at all.
The strategic point in the report deserves a direct quote: "Attackers have stopped trying to break trust relationships and started using the credentials that already make those relationships work." A worm with 469 paths is not exploiting anything. It is reading files your user account is allowed to read.
Why a developer workstation is the densest target in the building
Count what one engineer authenticates to on an ordinary day: GitHub, npm, AWS, a Kubernetes cluster, internal APIs, the build system. Each of those handshakes leaves residue on disk, because CLIs cache tokens so you do not have to re-authenticate constantly. The cache is a product feature. It is also the target.
A few properties make the workstation a better hunting ground than any server:
- Predictability.
~/.aws/credentialsis the same path on your laptop, my laptop, and the laptop of the engineer who joined last week. A list of 469 entries covers most of a fleet with zero reconnaissance. - Permission-free reads. An infostealer runs as the logged-in user. The file permissions that protect
/etc/shadowdo nothing for dotfiles the user owns. - Cross-domain authority. As the report notes, a secret found in one place can represent authority somewhere completely different. The token sitting in a CI config on disk may administer a production cluster.
The raw material keeps growing. GitGuardian's secrets sprawl research, cited in the coverage, counted 28.65 million new hardcoded secrets committed to public GitHub in 2025, a 34 percent year over year increase. That is what leaks into public view. The private residue on endpoints is larger and better organized.
One position I will defend: repository scanning is necessary hygiene, and it is also the wrong battlefield for this worm. Shai-Hulud does not need you to commit anything. It reads what your tooling already wrote to disk.
The taxonomy: what 469 paths on a dev machine actually look like
Here is the reconstruction, ranked by what an attacker can do with each tier.
| Tier | Where the paths live (examples) | What it buys the attacker |
|---|---|---|
| Package publishing | ~/.npmrc, ~/.pypirc, ~/.gradle/gradle.properties, ~/.cargo/credentials.toml, NuGet configs | The right to ship malware as a trusted maintainer |
| Cloud control plane | ~/.aws/credentials, ~/.aws/cli/cache, ~/.azure, ~/.config/gcloud | The account itself: data, compute, IAM |
| Cluster and deploy | ~/.kube/config, ~/.docker/config.json, Helm and Argo configs | Production workloads and registries |
| Source and forge | ~/.git-credentials, ~/.ssh, ~/.config/gh/hosts.yml, ~/.netrc | Private code, CI triggers, lateral movement |
| CI/CD leftovers | Local runner configs, pipeline variable exports, act-style env files | Build-time secrets, often production deploy creds |
| Environment residue | .env files, shell history, exported vars in ~/.zshrc and ~/.bashrc | The freshest tokens, pasted ad hoc and never rotated |
| IDE and editor state | settings.json, extension storage, REST client scratch files | Tokens pasted once for a test and forgotten |
| AI tooling configs | MCP server definitions, coding-agent provider keys, local model runtimes | API spend, data access, a surface almost nobody audits |
Package publishing at the top is the report's ranking, and it is correct; the rest of the ordering is mine. Publishing credentials convert theft into distribution. Steal one npm token and you do not just read someone's code, you push your code to everyone who trusts that package. "Attackers are hunting for reusable authority," the writeup says, and nothing reuses better than a publish token.
The new shelf: AI tool configs
The jump from 189 to 469 did not come from discovering new kinds of .env files. A serious chunk of it is the AI development stack, which writes credentials to disk with the enthusiasm of early npm and none of the hardening. MCP server configs carry plaintext API keys for every service the agent can touch. Coding agents store provider keys and session tokens in their config directories. Local model runtimes hold their own auth material and often listen on a socket; we published an audit and lockdown playbook for one of those flaws.
These agents also install dependencies at machine speed, which is one way a worm like this lands on the workstation in the first place. We covered that blind spot in the SBOM gap left by a coding agent's install spree. The AI shelf is the fastest-growing part of the credential surface and the least inventoried. Bad combination.
How the theft becomes distribution

The report describes a chain, and it reads better as a kill chain than as a metaphor:
workstation → source code → cloud credentials → infrastructure → package publication
Each hop is funded by whatever the previous one coughed up. "Credentials become the connective tissue between one compromised environment and the next." One syndicated rewrite describes this variant self-replicating across connected systems; the originating report does not establish that, and it does not need to. Tokens travel on their own. A kube config copied off one laptop works from any laptop.
Audit your own machine in five minutes
Run this before you ask anyone else to. It prints which credential paths exist, never their contents.
paths=(
~/.npmrc ~/.pypirc ~/.gradle/gradle.properties ~/.cargo/credentials.toml
~/.aws/credentials ~/.aws/cli/cache ~/.azure ~/.config/gcloud
~/.kube/config ~/.docker/config.json
~/.git-credentials ~/.netrc ~/.config/gh/hosts.yml ~/.ssh
)
for p in "${paths[@]}"; do [ -e "$p" ] && echo "PRESENT: $p"; done
find ~ -maxdepth 4 -name '.env*' -not -path '*/node_modules/*' 2>/dev/null | head -50Then check how git stores credentials, and scan shell history for token shapes, printing counts only:
git config --global credential.helper
# "store" means forge tokens sit in plaintext at ~/.git-credentials
for f in ~/.bash_history ~/.zsh_history; do
[ -f "$f" ] && printf '%s -> ' "$f" && \
grep -icE 'AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{20,}|npm_[A-Za-z0-9]{20,}|xox[bap]-' "$f"
doneAnything above zero in history means a token was pasted or exported on the command line, which means it also lives in scrollback and backups. For whatever the audit surfaces in AWS, aws sts get-caller-identity tells you whether the on-disk creds still work and which identity they map to. Validity first, then rotation.
At fleet scale, the detection tell is not any single file read, since your own processes touch dotfiles all day. The tell is one non-interactive process reading dozens of these paths within seconds. That is a query your EDR can express if you hand it the list above.
The fix list, in order
First: publishing credentials
This is the report's top priority and mine. Long-lived npm and registry tokens are the one tier where theft converts directly into malware distribution through a channel your customers already trust. The source points to recent moves by Docker and GitHub Actions toward stronger authentication and trusted publishing: GitHub Actions workload identity over OIDC, npm trusted publishing, AWS STS for short-lived cloud sessions. None of this requires buying anything. It requires deciding that a token which lives for a year in a dotfile is an incident that has not happened yet.
Then: everything production touches
The syndicated coverage lays out a sensible sequence, and I would not reorder it: cloud accounts, databases holding customer data, Kubernetes clusters, deployment systems, code-signing infrastructure, administrative interfaces. The move is the same at each stop. Short-lived credentials issued at runtime beat long-lived credentials cached on disk, because stolen short-lived ones expire before anyone gets to use them.
Finally: change what your secrets program measures
Here is the quiet argument in the report: "A list containing 100,000 secret findings does not represent 100,000 equally urgent incidents." Detection counts are a vanity metric. For every finding you need six answers: is it still valid, which identity does it represent, which systems accept it, what privileges does it carry, which environment can it reach, and who owns revoking it. A findings queue without those answers is a list of anxiety, not a work queue.
Yes, 469 is a vendor number
The skeptical read is that this is a secrets vendor selling a scanner and an OIDC pitch, and that the path count is unauditable because the list is private. Both true. I am amplifying it anyway, for one reason: the categories are checkable against your own disk tonight, the prescription is what I would tell you if the number were 69, and trusted publishing costs you nothing but some pipeline edits. Vendor research can be self-interested and still be right. This is.
If the audit above turned up tokens you cannot account for, the next question is where else your organization's keys have ended up. Leaked keys and forgotten cloud assets are an attack-surface problem. Axeploit is the scanner we use for that class of finding.
Key takeaways
- The 189 to 469 jump means the worm's authors gap-analyzed their own coverage. The developer workstation, not the perimeter, is the credential vault they are optimizing for.
- GitGuardian published categories, not paths. Reconstruct the list from the taxonomy above and audit against it, because the defaults are identical on every machine.
- Fix publishing credentials first. OIDC-based trusted publishing removes the one tier where theft becomes distribution.
- An infostealer runs as the user, so file permissions will not save you. Short-lived credentials will.
- Measure your secrets program by answered questions (valid? whose? reaches what? who rotates?) rather than finding counts.



