Три пакета для математических расчётов в репозитории npm - mathmain, mathsbase и math-universe - несут в себе скрытый загрузчик. Он умеет расшифровать посторонний код и запустить его в том же процессе, что и сама библиотека. Срабатывает механизм только при одном условии: вычислитель нужно вызвать с определёнными исходными данными. Обычная установка пакета или его подключение к чужому проекту ничего не запускают. Что именно скрыто в зашифрованных файлах, выяснить пока не удалось.
Описание
Пакет mathmain версии 1.0.0 опубликовали 17 сентября 2026 года. По виду он повторял известную библиотеку mathjs, только под другим именем, а часть кода в нём была намеренно запутана. Внимание привлёк лишний вызов в функции, которая решает системы линейных уравнений. Результат расчёта к тому моменту уже готов, и добавленный вызов на него не влияет. Никакой пользы для математики он не несёт. Авторы сборки никак его не объяснили.
Исследование SafeDep показало, что этот вызов ведёт к служебной проверке, спрятанной среди обычных функций. Она превращает входные данные в текстовую строку и использует её как пароль. Сначала расшифровывается имя файла, затем содержимое самого файла. Готовый код записывается на диск рядом с библиотекой и подключается к работающему процессу. Восстановленные строки и понятные имена переменных добавили при разборе, в исходном виде всё выглядело как набор бессмысленных символов.
Для защиты содержимого применяется стойкое шифрование с проверкой подлинности данных, а ключ выводится из пароля. Если пароль неверный, проверка целостности не проходит, и на диск ничего не попадает. В видимой части загрузчика пароля нет. Предположительно его должен предоставить тот, кто вызывает вычислитель: переданная матрица данных и становится ключом. Такое устройство позволяет хранить вредоносный код прямо в открытом репозитории, не выдавая его содержимого. Размер зашифрованных наборов разный, самый крупный превышает мегабайт.
Внутри библиотек лежат три файла, заполненных зашифрованными данными вместо обычного кода. Два из них в видимой части загрузчика никак не упомянуты. Кто и когда их подключает, пока неизвестно. Ни установочных сценариев, ни автоматических действий при подключении пакета в его описании нет.
Даты публикаций версий идут в необычном порядке. Первую сборку mathsbase выложили 26 августа 2026 года, и загрузчика в ней не было. Уже на следующий день появилась версия с ним. Пятнадцатого сентября вышла новая сборка без загрузчика, и её назначили версией по умолчанию. Пакет math-universe публиковали 16 сентября трижды, причём версия 1.0.1 появилась позже 1.0.2 - порядок номеров нарушен. Замыкает список mathmain 17 сентября.
Ещё два пакета содержат те же файлы загрузчика, тот же код запуска и те же правки в вычислителе. Совпадения прослеживаются в пяти версиях. Один из зашифрованных файлов в mathsbase отличается от остальных копий. Общие фрагменты связывают эти выпуски между собой, но не объясняют, кто добавил загрузчик и не была ли взломана учётная запись публикатора. Отдельно отмечается риск поверхностных проверок: тот, кто смотрит только на версию по умолчанию, версию с загрузчиком пропустит.
В открытых репозиториях на GitHub, указанных у mathsbase и math-universe, загрузчика нет. Публичный исходный код вычислителя заканчивается без лишнего вызова, который присутствует в сборке из npm. Поиск проектов, подключавших эти библиотеки или обращавшихся к вычислителю, тоже не дал результата. Ни один найденный потребитель не передавал нужный пароль. Частные приложения и проекты, отсутствующие в результатах поиска, остаются вне такой проверки.
Подобрать пароль не удалось. Сначала проверили почти семнадцать тысяч вариантов против зашифрованного имени файла, включая наборы чисел с нулями по диагонали матрицы, которые пропустили ранее. Во втором заходе испытали больше пятисот вариантов против всех пяти зашифрованных наборов. Проверяли и распространённые пароли, и числовые массивы из тестов вычислителя. Некоторые варианты повторялись в обоих поисках. Ни одна догадка не прошла проверку подлинности, хотя инструменты заранее протестировали на данных с известным паролем.
Рабочая версия такова: пакеты можно использовать как хранилище полезной нагрузки для будущей атаки. Отдельный пакет способен добавить такую библиотеку себе в зависимости и передать верный пароль. Тогда спусковой код окажется в одном пакете, а зашифрованное содержимое - в другом. Загрузчик такую схему поддерживает, но пакета, который пользуется ей, найти не удалось. В похожем расследовании SafeDep по пакету ulid-xyz цепочку до загрузчика проследить получилось. Здесь этого звена не хватает.
Загрузчик вызывает подозрения: он спрятан внутри вычислителя и отсутствует в открытом исходном коде. При этом доказательств кражи учётных данных, связи с чужим сервером или закрепления в системе нет. Установить назначение кода можно будет, когда найдётся вызывающая сторона с верным паролем либо само расшифрованное содержимое. Разработчикам стоит внимательнее относиться к составу зависимостей, фиксировать версии в файле блокировки и сверять сборки из репозитория с опубликованным исходным кодом.
Индикаторы компрометации
Package
- mathmain@1.0.0
- mathsbase@1.0.1
- math-universe@1.0.0
- math-universe@1.0.1
- math-universe@1.0.2
SHA256
- 03e13cdedd9c33e6fed25092b1ec7dcf11cc5962c0fbb6b3e90ba95bfec1b034
- 1723a0df210ac61281a504f3a07ec3605d20151631e0635cc344cacc71019135
- 4eb1d59df7dc80dbe3ec154481e61e8824422037092c188f0cc146b543615a66
- 5d9e952c51875d2b897eedc22b002b94ab21c8004d513bc99ce3a885f8a01dae
- 7e5e1bcdc6a7b0e3437269a236b49ef2be4f77081c7de5130d503c103fd6be69
- ab66c98e8ed5235feb963ec8845765f62f5f26b1c58c266c409767e53bcb5ccd
- bfe772e7ee044fd6f0bdf53e83f44aad7c9ee1925baf0cf4d884a312aa9ba50e