В экосистеме npm обнаружена масштабная кампания под названием PhantomRaven, в рамках которой злоумышленники разместили 126 вредоносных пакетов, собравших в совокупности более 86 000 установок. Эти пакеты активно похищают токены npm, учетные данные GitHub и секреты CI/CD у разработчиков по всему миру, при этом скрывая вредоносный код в зависимостях, остающихся невидимыми для большинства инструментов безопасности.
Описание
Обнаружение кампании произошло в октябре 2025 года, когда система мониторинга безопасности Wings компании Koi Security зафиксировала подозрительную активность. Пакеты совершали внешние сетевые запросы во время установки, причем все запросы направлялись на один и тот же подозрительный домен. Последующее расследование показало, что кампания действует с августа 2025 года, причем 80 пакетов оставались активными на момент обнаружения.
Инфраструктура злоумышленников оказалась удивительно небрежной для столь изощренной техники атаки. Были использованы последовательные учетные записи электронной почты от бесплатных провайдеров - jpdtester01@hotmail[.]com, jpdtester02@outlook[.]com и так до jpdtester13@gmail[.]com, а также имена пользователей вроде npmhell или npmpackagejpd, явно контролируемые одним лицом.
Ключевой особенностью PhantomRaven стала техника Remote Dynamic Dependencies (RDD), позволяющая скрывать вредоносный код от систем безопасности. В отличие от обычных зависимостей, которые указываются в стандартном формате, злоумышленники использовали HTTP-URL в качестве спецификаторов зависимостей. Когда разработчик устанавливает такой пакет, npm загружает зависимость с внешнего URL, а не из официального реестра npmjs.com.
Это создает серьезную проблему для систем безопасности: npmjs.com не отслеживает эти внешние URL, сканеры безопасности не проверяют их, а инструменты анализа зависимостей их игнорируют. Для всех автоматизированных систем безопасности такие пакеты отображаются как имеющие "0 зависимостей", хотя на самом деле содержат скрытую вредоносную нагрузку.
Каждый раз при выполнении команды npm install зависимость загружается заново с сервера злоумышленников, что дает им полный контроль над тем, какой код получает жертва. Теоретически это позволяет осуществлять целенаправленные атаки: определять IP-адрес запроса и предоставлять различные варианты кода - безвредный код исследователям безопасности, вредоносный код корпоративным сетям или специализированные нагрузки для облачных сред.
Автоматическое выполнение кода обеспечивается через хуки жизненного цикла npm. Вредоносный пакет, загружаемый через RDD, содержит скрипт preinstall, который выполняется автоматически при установке без какого-либо предупреждения или взаимодействия с пользователем. Это происходит независимо от того, насколько глубоко в дереве зависимостей находится вредоносный пакет.
Функциональность PhantomRaven включает систематический поиск email-адресов во всей среде разработки, включая переменные окружения, конфигурационные файлы Git и npm. Затем malware собирает учетные данные CI/CD-систем, включая токены GitHub Actions, учетные данные GitLab CI, Jenkins и CircleCI, а также токены аутентификации npm.
Завершающий этап включает полное fingerprinting системы с сбором информации о публичном IP-адресе, имени хоста, деталях операционной системы, локальном IP, имени пользователя, текущем каталоге и версии Node.js. Экстракция данных осуществляется через несколько каналов: HTTP GET и POST запросы, а также резервное WebSocket-соединение для обхода ограничений сетевых сред.
Особенностью кампании стало использование техники "slopsquatting" - регистрации пакетов с именами, которые искусственный интеллект может галлюцинировать при рекомендации пакетов разработчикам. Например, вместо существующего пакета eslint-plugin-eslint-comments злоумышленники регистрировали eslint-comments, что делает атаку более эффективной, так как разработчики доверяют рекомендациям AI-ассистентов.
Обнаружение PhantomRaven подчеркивает растущую сложность угроз в экосистеме open-source и необходимость более совершенных подходов к безопасности, учитывающих современные техники обхода защиты.
Индикаторы компрометации
IPv4
- 54.173.15.59
Domains
- packages.storeartifact.com
Compromised Packages
- fq-ui
- mocha-no-only
- ft-flow
- ul-inline
- jest-hoist
- jfrog-npm-actions-example
- @acme-types/acme-package
- react-web-api
- mourner
- unused-imports
- jira-ticket-todo-comment
- polyfill-corejs3
- polyfill-regenerator
- @aio-commerce-sdk/config-tsdown
- @aio-commerce-sdk/config-typedoc
- @aio-commerce-sdk/config-typescript
- @aio-commerce-sdk/config-vitest
- powerbi-visuals-sunburst
- @gitlab-lsp/pkg-1
- @gitlab-lsp/pkg-2
- @gitlab-lsp/workflow-api
- @gitlab-test/bun-v1
- @gitlab-test/npm-v10
- @gitlab-test/pnpm-v9
- @gitlab-test/yarn-v4
- acme-package
- add-module-exports
- add-shopify-header
- jsx-a11y
- prefer-object-spread
- preferred-import
- durablefunctionsmonitor
- durablefunctionsmonitor-vscodeext
- durablefunctionsmonitor.react
- e-voting-libraries-ui-kit
- named-asset-import
- chai-friendly
- aikido-module
- airbnb-babel
- airbnb-base-hf
- airbnb-base-typescript-prettier
- airbnb-bev
- airbnb-calendar
- airbnb-opentracing-javascript
- airbnb-scraper
- airbnb-types
- ais-sn-components
- goji-js-org
- google-cloud-functions-framework
- chromestatus-openapi
- elemefe
- labelbox-custom-ui
- rxjs-angular
- @apache-felix/felix-antora-ui
- @apache-netbeans/netbeans-antora-ui
- syntax-dynamic-import
- no-floating-promise
- no-only-tests
- @i22-td-smarthome/component-library
- vuejs-accessibility
- lfs-ui
- react-async-component-lifecycle-hooks
- eslint-comments
- wdr-beam
- lion-based-ui
- lion-based-ui-labs
- eslint-disable-next-line
- eslint-github-bot
- eslint-plugin-cli-microsoft365
- eslint-plugin-custom-eslint-rules
- @item-shop-data/client
- @msdyn365-commerce-marketplace/address-extensions
- @msdyn365-commerce-marketplace/tax-registration-numbers
- artifactregistry-login
- crowdstrike
- wm-tests-helper
- external-helpers
- react-important-stuff
- audio-game
- faltest
- only-warn
- op-cli-installer
- react-naming-convention
- skyscanner-with-prettier
- xo-form-components
- xo-login-components
- xo-page-components
- xo-shipping-change
- xo-shipping-options
- xo-title
- xo-tracking
- xo-validation
- badgekit-api-client
- important-stuff
- transform-es2015-modules-commonjs
- transform-merge-sibling-variables
- transform-react-constant-elements
- transform-react-jsx-source
- transform-react-remove-prop-types
- transform-strict-mode
- trezor-rollout
- filename-rules
- ing-web-es
- inline-react-svg
- ts-important-stuff
- firefly-sdk-js
- firefly-shared-js
- zeus-me-ops-tool
- zeus-mex-user-profile
- ts-migrate-example
- ts-react-important-stuff
- zohocrm-nodejs-sdk-3.0
- iot-cardboard-js
- pensions-portals-fe
- sort-class-members
- sort-keys-fix
- sort-keys-plus
- flowtype-errors
- twilio-react
- twilio-ts
- bernie-core
- bernie-plugin-l10n
- spaintest1
- typescript-compat
- typescript-sort-keys
- uach-retrofill
Attacker Infrastructure
- npmjjjj (jpdtester01@hotmail.com)
- npmjpd2 (jpdtester02@outlook.com)
- npmtestdharsh (jpdtester03@outlook.com)
- npmtesthas1 (jpdtester05@outlook.com)
- packagejpd (jpdtester06@outlook.com)
- npmhell (jpdtester07@hotmail.com)
- npmpackagejpd (jpdtester07@outlook.com)
- onlynpmpackagejpd (jpdtester08@hotmail.com)
- micropackage1 (jpdtester09@outlook.com)
- npmpackagejpd12 (jpdtester10@hotmail.com)
- jpdhackerone11 (jpdtester11@outlook.com)
- jpd12 (jpdtester12@gmail.com)
- packagedharsh (jpdtester12@outlook.com)
- jpd13 (jpdtester13@gmail.com)