Use when investigating a cryptocurrency wallet-stealer or supply-chain infection in a JS/TS repository, when build-config files (postcss.config, .eslintrc, jest.config, vite.config, etc.) look suspicious, when an audit finds obfuscation markers, multi-thousand-character lines, or createRequire shims in source files, when forged-commit timezone mismatches are suspected, or when hardening a JS/TS repo against the 2026-Q2 wallet-stealer incident family.
How this skill is triggered — by the user, by Claude, or both
Slash command
/wallet-stealer-defense:wallet-stealer-defenseThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Detect, purge, and harden against the 2026-Q2 wallet-stealer / supply-chain malware family (a single operator/toolkit observed across multiple JS/TS repositories). The payload hides as a tail on build-config files behind whitespace padding, runs on routine tooling (`next dev`, ESLint, jest, vite), and exfiltrates credentials & wallet seeds via public-blockchain RPC dead-drops.
Detect, purge, and harden against the 2026-Q2 wallet-stealer / supply-chain malware family (a single operator/toolkit observed across multiple JS/TS repositories). The payload hides as a tail on build-config files behind whitespace padding, runs on routine tooling (next dev, ESLint, jest, vite), and exfiltrates credentials & wallet seeds via public-blockchain RPC dead-drops.
*.config.{js,mjs,cjs,ts}, .eslintrc*) has a single line >4000 chars_$_1e42, _$af163278, _$_ccfc, or global['!']='9-XXXX-X'.config.mjs files import createRequire(import.meta.url) alongside a very long lineapi.trongrid.io / aptoslabs.com / bsc-dataseed.binance.org references in source-0700/-0800) doesn't match author timezone (+0200/+0800/+0900)Not for: generic npm audit issues, unrelated supply-chain CVEs (e.g. event-stream, node-ipc), or non-JS ecosystems.
1. DETECT → scripts/scan.sh in the repo root; or invoke iocs.md grep set manually
2. PURGE → auto-heal known carriers (postcss/eslintrc) via scripts/restore-carrier.sh;
for unknown carriers, show finding and ASK before modifying
3. HARDEN → install templates/malware-scan.yml + templates/gitattributes + templates/editorconfig,
THEN install a husky scan hook adapted to the project (mandatory; see 3b)
Run the bundled scanner from the repo root:
bash ~/.claude/skills/wallet-stealer-defense/scripts/scan.sh
Exit code 0 = clean. Exit code 1 = one or more IoCs found; specific findings printed.
The scanner checks six IoC classes (full catalog in iocs.md):
_$_1e42, _$af163278, _$_ccfc)global['!']='9-XXXX-X').js/.mjs/.cjs/.ts/.tsx/.jsx*.config.mjs files mixing createRequire(import.meta.url) with a long lineFor commit-metadata forensics (forged-author detection):
git log --all --pretty=format:'%h %ai author=%ae | %ci committer=%ce' --since="1 year ago" \
| awk '/[+-][0-9]{4}/ {
match($0, /[0-9]{4} author/); a=substr($0, RSTART, 5);
match($0, /[0-9]{4} committer/); c=substr($0, RSTART, 5);
if (a != c && (c ~ /-07/ || c ~ /-08/)) print
}'
Known carriers — auto-heal. Run:
bash ~/.claude/skills/wallet-stealer-defense/scripts/restore-carrier.sh <path>
Supports postcss.config.{js,mjs,cjs} and .eslintrc.js. Strategy:
import { createRequire } shim line if present; truncate at first standalone export default config; or module.exports terminator; remove tail; verify wc -c is small and no IoC marker remains.}; (the module.exports terminator — inner blocks use },). Preserves legitimate config verbatim.After restore, verify:
grep -E '_\$_1e42|_\$af163278|_\$_ccfc|global\[..!..\]' <path> # expect empty
awk '{if(length>m)m=length}END{print FILENAME": max line "m+0}' <path> # expect small
Unknown carriers — ASK before modifying. If the scanner flags a file that isn't a known carrier:
git log -p -S 'global[..!..]' -- <path> and git log --follow --oneline <path> to find the introducing commit.git show <sha>:<path> from before the long-line first appeared).<path> to its content at commit <clean-sha>? Or strip the tail manually?"Never force-push, never git filter-repo without explicit user consent. Cleanup uses fast-forward commits authored by a <repo>-security-response identity — preserves blame.
After purge, if any developer ran tooling (next dev, next build, ESLint, jest) on the infected branch: the payload may have executed locally. Tell the user to rotate from a clean device: .env secrets, JWT secret, DB creds, GitHub PATs, SSH keys, npm tokens, cloud creds, and move crypto wallet funds first.
Detection-only hardening (per the chosen mode). Install three files at the repo root:
# CI scanner — fails any push/PR reintroducing IoCs
mkdir -p .github/workflows
cp ~/.claude/skills/wallet-stealer-defense/templates/malware-scan.yml \
.github/workflows/malware-scan.yml
# LF enforcement at commit time (defeats whitespace/CRLF camouflage)
cp ~/.claude/skills/wallet-stealer-defense/templates/gitattributes .gitattributes
# LF enforcement at editor save time
cp ~/.claude/skills/wallet-stealer-defense/templates/editorconfig .editorconfig
git add .github/workflows/malware-scan.yml .gitattributes .editorconfig
git commit -m "security: add malware signature scan + LF enforcement"
If the target repo already has these files, diff first and merge — do not overwrite user content.
The CI workflow excludes node_modules/, .git/, dist/, build/, .next/, coverage/, and any docs/security/ directory (so docs documenting the IoCs don't self-trip the scanner).
A local hook is mandatory — CI is the backstop, but the husky hook catches the carrier before it ever leaves the dev's machine. It must not be a generic copy-paste: install it only after understanding the project, adapt it to the project's setup, and verify the project's own hooks and build still run fine afterward. Use a detection-based hook (run the scan), never the old hash-pinned self-heal — the per-project SHA-256 was brittle and is abandoned.
Step 1 — understand the project first. Before touching anything, inspect:
.husky/ — which hooks exist (pre-commit, pre-push, commit-msg) and what they already run (lint-staged, tests, tsc).package.json — the prepare script (husky / husky install), husky version (v9+ uses bare hook scripts; v8 and earlier need the . "$(dirname -- "$0")/_/husky.sh" boilerplate), and any lint-staged config.prepare flow.Step 2 — vendor the scan into the repo. The hook runs on every developer's machine and in CI, so it cannot reference ~/.claude/.... Copy the scanner into the repo:
mkdir -p scripts/security
cp ~/.claude/skills/wallet-stealer-defense/scripts/scan.sh scripts/security/malware-scan.sh
chmod +x scripts/security/malware-scan.sh
Step 3 — merge the guard into an existing hook, preserving the project's rules. Pick the hook by scan cost: pre-commit (earliest, but runs every commit) for small repos; pre-push for large repos where the scan is slow. Append the guard block from templates/husky-malware-scan.sh to the chosen hook — never overwrite the project's existing hook commands. If the hook doesn't exist yet, create it matching the project's husky version format.
# Example: append to an existing pre-commit (do NOT clobber lint-staged etc.)
cat ~/.claude/skills/wallet-stealer-defense/templates/husky-malware-scan.sh >> .husky/pre-commit
Step 4 — verify the project still runs fine. This is the acceptance gate:
wc -c / grep on the carrier, not by running next dev/next build (that's the execution surface).If anything in the project's own workflow breaks, fix the adaptation (hook choice, ordering, or husky boilerplate) — do not leave the project unable to commit.
Still require per-project tuning (mention as follow-ups, not auto-installed):
git filter-repo history purge of any plaintext .env* secrets — destructive, needs a clean machine, and the team must coordinate force-push.| Class | Signal | Strongest in |
|---|---|---|
| Obfuscation | _$_1e42, _$af163278, _$_ccfc | source files |
| Watermark | global['!']='9-XXXX-X' (9-3803-1, 9-4391-1, 9-4884, 9-4955-1) | source files |
| C2 hosts | api.trongrid.io, fullnode.mainnet.aptoslabs.com, bsc-dataseed.binance.org, bsc-rpc.publicnode.com | source/config files |
| C2 wallets | TMfKQEd7TJJa5xNZJZ2Lep838vrzrs7mAP, TXfxHUet9pJVU1BgVkBAbrES4YUc1nGzcG | source files |
| Structural | line >4000 chars in .js/.mjs/.cjs/.ts/.tsx/.jsx | build-config files |
| ESM re-entry | createRequire(import.meta.url) + long line in *.config.mjs | build-config files |
| Forensic | committer tz -0700/-0800 ≠ author tz +0200/+0800/+0900 | git history |
Full catalog with context, false-positive notes, and per-class grep recipes: iocs.md.
.gitignore — it controls tracking only; the payload reads disk as a running process. .gitignore is not a security control.-w — whitespace-padding camouflage hides the payload past the visible diff. Always use git diff -w <range> on review.--ff-only from a verified-clean remote; rebase work onto cleaned dev/main.next dev or next build to test the fix — that's the execution surface. Verify with wc -c and grep instead.git filter-repo without team coordination — destroys other developers' work and breaks open PRs. The reference incident used surgical fast-forward cleanup commits instead.iocs.mdscripts/scan.shscripts/restore-carrier.shtemplates/malware-scan.ymltemplates/husky-malware-scan.shtemplates/gitattributes, templates/editorconfigjest.config.js carrier; has standalone forensic decoder scripts.Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.
npx claudepluginhub peter-mfitumukiza/wallet-stealer-defense --plugin wallet-stealer-defense