Первого июля 2026 года пользователь npm marketfront за три минуты опубликовал 25 пакетов в область @marketfront. Все пакеты имели версию 7.0.0 и содержали постинсталляционный сборщик учётных данных. В README каждого пакета значилась одна и та же строка: "Internal package - Platform Engineering Team". Эта строка не указывает на конкретный аккаунт, а представляет собой многоразовый шаблон, использующий технику dependency confusion. Набор пакетов имитировал внутренние модули для фронтенда интернет-магазина - header, footer, navbar, bannerpopup, customdealsfeed и другие.
Описание
Специалисты SafeDep отслеживают эту кампанию с мая 2026 года. Ранее были зафиксированы волны с участием аккаунтов mr.4nd3r50n, pik-libs, t-in-one и emcd-vue, которые публиковали пакеты в областях @cloudplatform-single-spa, @t-in-one, @emcd-vue и других. Об этом сообщается в отчёте SafeDep, где документируется вся кампания под названием oob.moika.tech. Реестр npm уже удалил пакеты @marketfront, однако шаблон сохранился в действующей области @emcd-vue, которая была перевыпущена с новыми версиями - @emcd-vue/auth@7.1.0, @emcd-vue/loans@7.2.0, @emcd-vue/b2b-pay-form@5.8.0. Эти артефакты побайтно совпадают с шаблоном, что позволило SafeDep провести статический анализ.
Вредоносная кампания эксплуатирует механизм dependency confusion. Если проект использует имя пакета, соответствующее внутреннему пространству имён, но не заблокировал его в частном реестре, менеджер пакетов npm может разрешить публичную версию вместо отсутствующей приватной. Именно так злоумышленники добиваются выполнения своего кода на рабочих станциях разработчиков и в сборочных конвейерах CI. Пакеты @marketfront имитируют внутренние модули конкретной организации, что повышает шансы на срабатывание атаки.
После установки пакета npm выполняет скрипт "scripts/postinstall.js". Этот скрипт представляет собой одну строку обфусцированного кода размером около 160 КБ, созданного с помощью obfuscator.io. Первый уровень обфускации - стандартная перестановка строк через модифицированный алфавит base64. Однако чувствительные строки скрыты за вторым слоем шифрования RC4 с ключом для каждой строки. Из-за этого пути к файлам учётных данных и адрес командного сервера не видны при статическом дампе строк. SafeDep восстановил логику поведения методом статической декомпиляции.
Полезная нагрузка обращается к модулям "fs", "os", "http", "https", "zlib", "path" и "dns". Она читает около 20 файлов, содержащих учётные данные: ключи SSH из "~/.ssh", облачные credentials ("~/.aws/credentials", "~/.kube/config", "~/.docker/config.json"), токены реестров и пакетов ("~/.npmrc"), сетевые и базовые secrets ("~/.netrc", "~/.pgpass"), git-credentials ("~/.git-credentials"), файлы окружения и историю команд ("~/.env", "~/.bash_history"). Собранные данные сжимаются в gzip и отправляются через HTTPS POST с кастомным заголовком "X-Secret" по пути "/api/v1/events". Дополнительно выполняется DNS-запрос на командный сервер. Адрес сервера скрыт за слоем RC4 и XOR вокруг встроенного блока конфигурации. SafeDep не восстанавливал его без выполнения кода.
Шаблон README и метаданные остаются неизменными на протяжении всей кампании, в то время как полезная нагрузка эволюционирует. Первая волна в конце мая использовала версии 99.99.99, собирала переменные окружения и отправляла их на сервер oob.moika.tech. Волна в начале июня применяла более сложную обфускацию WaCk/JScrambler, устанавливала персистентность в домашний каталог и использовала рукопожатие второго этапа FUSION. Версия от 1 июля перешла к целевому сбору файлов учётных данных с шифрованием командного сервера. Версионные номера при этом стали выглядеть естественно - 7.0.0, 7.1.0, 7.2.0, что не срабатывает на эвристиках, проверяющих аномальные версии вроде 99.99.99.
Два элемента остались постоянными: маркер README "Internal package - Platform Engineering Team" с подставными доменами вроде docs.<scope>.io и jira.<scope>.io, а также заголовок X-Secret в исходящих запросах. Этот маркер является дешёвым элементом атаки, но его трудно использовать для обнаружения на поисковых серверах npm, так как поиск не индексирует содержимое README, а свежие пакеты с нулевыми загрузками получают низкий приоритет.
Для выявления подобных угроз SafeDep рекомендует использовать сигнатуры метаданных и поведения. К таким сигнатурам относятся: постинсталляционный скрипт "node scripts/postinstall.js" с однострочным обфусцированным пайлоадом, автор поля "author", заканчивающийся на "Platform Engineering", подставные домены в полях "repository.url", "bugs.url", "homepage", описание, взятое из фиксированного набора "Internal … loader / logger / client", и исходящий трафик во время установки с заголовком X-Secret.
Меры защиты включают блокировку каждой внутренней области в файле ".npmrc" для частного реестра. Без такой блокировки менеджер пакетов будет обращаться к публичному реестру, когда приватная версия недоступна. Если какой-либо пакет @marketfront версии 7.0.0 был установлен на рабочую станцию или сборочный узел, систему следует считать скомпрометированной. Необходимо немедленно ротировать ключи SSH, облачные учётные данные, токены npm, git-credentials и любые secrets, присутствовавшие в "~/.env" или окружении. Рекомендуется также проверять сетевые журналы на наличие HTTPS-запросов с заголовком X-Secret по пути "/api/v1/events" и на необычную активность DNS во время выполнения npm install. Добавление указанных сигнатур метаданных и поведения в правила триажа позволит автоматически выявлять следующие ротации области, не ожидая ручного обнаружения.
Индикаторы компрометации
Package
- @marketfront/actualordersnippetpopup
- @marketfront/advertisingdevtool
- @marketfront/bannerpopup
- @marketfront/baobabtech
- @marketfront/basemarkettemplate
- @marketfront/blenderdevtool
- @marketfront/captchaservice
- @marketfront/changefilter
- @marketfront/commonecommerce
- @marketfront/customdealsfeed
- @marketfront/designsystemdevtool
- @marketfront/devtoolsloader
- @marketfront/digitalherobannercarousel
- @marketfront/dynamicpageparams
- @marketfront/errorcounter
- @marketfront/fashiononboardingpopup
- @marketfront/fingerprint
- @marketfront/footer
- @marketfront/gotoauthpopup
- @marketfront/header
- @marketfront/infopopup
- @marketfront/livestreampreviewpopup
- @marketfront/madvpopup
- @marketfront/mychatspreloader
- @marketfront/navbar