What secrets to expect on your filesystem

tl;dr A supply chain worm does not need an exploit. It runs as you, reads the credential files your tools leave on disk, and uses them to publish the next poisoned package. You will not get a developer machine to zero secrets. You can know exactly which ones to expect, and clear out the ones that were never supposed to be there.

The worm did not break in

Modern supply chain malware does not need an exploit. It runs the moment a poisoned postinstall script or a trojanized dependency executes, with your account and your file permissions. As far as the operating system is concerned, it is you.

So it does the cheapest thing available. It walks your home directory, reads the plaintext credential files your tools left behind, and puts them to work. Find an npm publish token and it ships a poisoned version of a package you maintain. That version runs on the next machine and the loop starts over.

SPREADS1Runs as youpoisoned install2Reads your diskcreds in plaintext3Publishes a packageuses your npm token4Next machineloop repeats

Why this is a challenge

A developer machine is going to have secrets on it. That is how the tools work. The AWS CLI needs a credential to call AWS. npm needs a token to publish. kubectl needs a way into the cluster. Strip every credential off the box and it stops being useful.

You will never get a laptop to zero secrets, and chasing that wastes your time. Two things are worth doing instead. Know which secrets to expect, because that is most of what a scan finds. Then clear out the smaller pile that had no reason to be there.

What you should expect to find

Most of what a scan turns up is not a mistake. It is the cost of the tools working. Every CLI you log into writes a credential to a known place so it does not have to ask again. gh auth login writes a GitHub token. npm login drops a publish token in ~/.npmrc. gcloud auth login caches a refresh token. These files sit in well known spots by design, which is also the map the worm reads.

Here is a typical home directory. The highlighted files are the ones an attacker opens first.

trufflehog filesystem ~
~
├── .aws/
│ └── credentials # AWS
├── .ssh/
│ ├── id_ed25519 # PrivateKey
│ └── id_ed25519.pub
├── .config/
│ ├── gh/hosts.yml # GitHub token
│ └── gcloud/ # refresh token + ADC
├── .npmrc # NpmToken publish access
├── .docker/config.json # registry auth
├── .kube/config # cluster tokens + certs
└── project/.env # the most common hit of all

The full picture is wider than the crown jewels. Below is the map by tool. Filter by category or search for the thing you use. Each row is a file a credential lands in, what writes it, and the TruffleHog detector that catches it.

Field guide · what lands on a developer machine, and whether you can move it somewhere safer

7 locations
Can move to a keychain / short-lived tokenPartial, depends on OSPlaintext, hard problem
~/.aws/credentials
Short-lived
aws configureLong-lived access key + secretAWS
~/.config/gcloud/
Plaintext, hard problem
gcloud auth loginRefresh token + ADCGCP
~/.config/gh/hosts.yml
Keychain / helper
gh auth loginGitHub token / PATGitHub
~/.ssh/id_ed25519, id_rsa
Encryptable
ssh-keygenSSH private keysPrivateKey
~/.npmrc
Plaintext, hard problem
npm loginPublish _authTokenNpmToken
~/.kube/config
Short-lived
kubectl / get-credentialsCluster tokens + certsPrivateKey
.env / .env.*
Plaintext, hard problem
dotenvKeys for everything abovemany

None of this is exotic. It is the default behavior of tools you use every day. Assume these files exist on every machine you run. The guide below also says, per tool, whether you can move the credential into the OS keychain or a short lived token, or whether plaintext on disk is just the reality you manage and rotate around.

The other pile: keys someone put there by hand

A smaller share of findings had no reason to be on the machine at all. A long lived AWS key pasted into ~/.aws/credentials because SSO felt like a chore. A service account JSON downloaded to ~/Downloads. An API key dropped into a .env to get a script running, then forgotten. A database URL with the password inline, sitting in shell history. These belong in a secret manager. This is the pile you can actually shrink, so start here.

What a scan will not catch

A filesystem scan reads files, so some things stay out of reach. It will not crack your macOS Keychain, Windows Credential Manager, or gnome keyring. It will not open an encrypted vault like Bitwarden or a pass store without the key. It cannot read a secret that only lives in a running process or sits on a hardware key.

The encouraging trend is that more tools move credentials into the keychain every release. The catch is how many still default to a plaintext file in your home directory, and how often the keychain first tools fall back to plaintext on Linux, WSL, and CI.

Check your machine the way the worm would

You do not need the malware to learn what it would have taken. Point TruffleHog at your home directory and let it walk the same paths.

scan it the way the worm would
# high-signal pass over a home directory
trufflehog filesystem ~ \
  --only-verified \
  --no-update \
  --concurrency=8 \
  --json > findings.json
# whole host: run as root to reach other users, /etc, /proc
sudo trufflehog filesystem / \
  --no-update \
  --json > host-findings.json

Then sort the results by detector. The shape of that list tells you which pile you are standing in, and where the cleanup starts.

Treat the laptop like production

The worm was not sophisticated. It ran as you, opened files your tools had already written, and used what it found. The credentials it wants are sitting in known locations on your machine right now. Some of them have to be there. A lot of them do not. Worth finding out which is which before something else does.

infra