Seven checks you can run right now
No tools required, nothing to install. Run these against any clone on your machine — the whole thing takes a couple of minutes. Every command is read-only; none of them change anything.
1 · Is a loader running right now?
ps -eo pid,args | grep -E "node .*-e .*global\[" | grep -v grep
No output means nothing is running. Any output is a live process — kill it.
2 · Does any file carry the operator's wallet?
grep -rn "0xa322E5f3D311D3080e6f0121063e9aDC2490Ef1a" .
git log --all -S "0xa322E5f3" --pickaxe-regex --oneline
3 · Is a task set to run when you open the folder?
grep -rn "folderOpen" .vscode/tasks.json
Any hit executes the moment the folder opens. Treat it as hostile until proven otherwise.
4 · Are your font files actually fonts?
head -c 4 public/fonts/*.woff2
Every real font prints wOF2. Spaces mean you are looking at a script.
5 · Do your npm scripts run something extra?
This family leaves every script you had and prefixes each one, so the file still looks
like yours. The payload runs on npm run dev — no install needed, which is why
--ignore-scripts does not help.
node -e 'const s=require("./package.json").scripts||{};
for (const [k,v] of Object.entries(s)) if (/\bnode\s+\S+\.[cm]?js/.test(v)) console.log(k, "->", v)'A build step calling your own scripts/build.js is normal. A root
api.js or app.js you did not write is not — open it and look at the
first line.
6 · Does your AI assistant run something at every session?
An agent's own config is an execution vector, and removing the package that delivered the hook does not remove the hook.
cat .claude/settings.json .claude/settings.local.json 2>/dev/null ls -la .claude/setup.mjs .vscode/setup.mjs 2>/dev/null
A hook you wrote — a formatter, a linter — is fine. node
.vscode/setup.mjs is a dropper, and the copies in .claude/ and
.vscode/ re-create each other, so remove both.
7 · Has someone rewritten your remote?
The remote tip comes back with your commit's subject, author and date under a different
hash. Git reports 1 ahead, 1 behind with identical messages, which reads as
harmless — and then a pull merges it.
git fetch && git log --format='%H %cI %s' HEAD..@{u}
git log --format='%H %cI %s' @{u}..HEADSame message and author date on both sides, but a different hash and a committer timezone that is not yours? Do not pull.
Look for the long line
The most reliable giveaway is geometry, not content. This finds any file padded out to hide something past the edge of the screen — a hand-written config has no business being 9,000 characters wide.
awk 'length > 1500 {print FILENAME": line "FNR" ("length" chars)"}' \
$(find . \( -name "*.js" -o -name "*.mjs" -o -name "*.cjs" \) -not -path "*/node_modules/*")Read the outcome carefully
Do not clean the repository first. Rotate your credentials before anything else — the order genuinely matters, and getting it wrong means doing the work twice.
Nothing matched Install snare to keep it that wayThese seven checks cover one clone at one moment. snare runs them continuously, across every repository you can reach, and blocks a push that would carry a payload out.
A clean result is narrower than it looks
Checks 2, 3 and 4 test one clone — not your other repositories, and not the branches you do not have checked out. Check 1 reports what is running right now; the loader fires when a build runs or an editor opens the folder, does its work, and exits, so a quiet process list alongside an infected repository is the expected result, not a contradiction.
These checks also key on this operator's wallet. A variant using a different address passes check 2 and is still caught by the long-line heuristic above — which is why that one matters most.