17 июня 2026 года произошёл масштабный инцидент в цепочке поставок программного обеспечения. Злоумышленник получил контроль над учётной записью одного из мейнтейнеров проекта Mastra - открытого TypeScript-фреймворка для создания AI-агентов, многошаговых рабочих процессов и систем генерации с дополнением (RAG). Используя скомпрометированные учётные данные, атакующий за 27 минут перевыпустил все 116 пакетов, входящих в организацию @mastra, добавив в каждый из них единственную новую строку зависимости - от пакета easy-day-js. Mastra является популярным инструментом, его компоненты загружаются более 28 миллионов раз в месяц, что делает атаку особенно опасной для всей экосистемы разработки на Node.js.
Описание
easy-day-js представляет собой тайпсквоттинг (имитацию) популярной библиотеки для работы с датами dayjs. Пакет копирует описание dayjs ("2KB immutable date time library alternative to Moment.js"), поставляет оригинальный dayjs.min.js в качестве основного модуля и включает все локали и плагины. Единственное функциональное отличие вредоносной версии 1.11.22 - наличие файла setup.cjs и одноимённого скрипта в postinstall в package.json. Именно этот скрипт является дроппером, который выполняется при каждой установке пакета.
Технический анализ показал, что атака была тщательно подготовлена. Анализ инцидента выявил, что за день до основной атаки, 16 июня, пользователь sergey2016 опубликовал "чистую" версию easy-day-js@1.11.21, не содержащую вредоносного кода. Эта версия была внедрена в качестве зависимости в пакеты Mastra с указанием "^1.11.21". Такая запись предписывает npm при установке выбирать самую свежую минорную или патч-версию, удовлетворяющую маске. 17 июня в 01:01 UTC была опубликована версия 1.11.22 с дроппером, и с этого момента каждая новая установка @mastra-пакета автоматически загружала и выполняла вредоносный postinstall-скрипт.
Процесс публикации шёл в автоматическом режиме. Все 116 пакетов были перевыпущены с 01:12 до 02:39 UTC, причём порядок определялся количеством загрузок: сначала обрабатывались самые популярные, такие как "@mastra/schema-compat" (более 5 миллионов загрузок в месяц), "@mastra/core" (4 миллиона), "mastra" (2,1 миллиона). Каждый новый релиз был выполнен вручную, вне CI/CD-пайплайна проекта, что подтверждается отсутствием SLSA-аттестатов происхождения (provenance) - механизма, подтверждающего, что пакет собран в официальной инфраструктуре репозитория.
Скрипт setup.cjs имеет размер 4,5 килобайта и обфусцирован с использованием трёхуровневой защиты: собственного алфавита Base64, ротации строкового массива с арифметической проверкой целостности и XOR-кодирования меток. После деобфускации выявляется следующая последовательность действий. Дроппер отключает проверку TLS-сертификатов, устанавливая переменную окружения "NODE_TLS_REJECT_UNAUTHORIZED = '0'". Затем он записывает в домашний каталог жертвы два маркерных файла: .pkg_history и .pkg_logs, которые содержат путь установки пакета и закодированное имя пакета. Далее дроппер загружает полезную нагрузку второй стадии с IP-адреса 23.254.164.92:8000 по URL "/update/49890878". Поскольку проверка сертификатов отключена, соединение с голым IP-адресом не вызывает ошибок. Загруженный код записывается во временный каталог под случайным именем (12 байт в hex + .js) и запускается как отсоединённый (detached) скрытый процесс, который продолжает работу после завершения установки npm. На Windows процесс дополнительно скрывается с помощью флага "windowsHide: true". После запуска дроппер удаляет сам себя вызовом "fs.rmSync(__filename, { force: true })", чтобы замести следы.
Вскоре после обнаружения стало ясно, что полезная нагрузка второй стадии более недоступна: URL "/update/49890878" возвращает ответ "not found". Однако сам факт существования дроппера и его поведение указывают на намерение получить доступ к окружению разработчика, где хранятся ключи API LLM (OpenAI, Anthropic, Google), облачные учётные данные (AWS, Azure), строки подключения к базам данных и токены CI/CD. Эксплуатация этих ресурсов могла привести к массовому хищению конфиденциальной информации и дальнейшему распространению атаки на другие системы.
Масштаб инцидента исключительно велик. Суммарная еженедельная аудитория скомпрометированных пакетов превышает 1,1 миллиона загрузок. Разработчикам, использовавшим любые пакеты @mastra в день 17 июня, рекомендовано считать свои окружения скомпрометированными, немедленно зафиксировать версии на последние проверенные релизы с тех пор, как была подтверждена их целостность (provenance-backed), и провести ревизию на предмет следов исполнения второго этапа. В качестве индикаторов компрометации выступают файлы .pkg_history и .pkg_logs в домашней или временной директории, а также любые неожиданные процессы, запущенные из временной папки.
Атака на Mastra демонстрирует растущую изощрённость атак на цепочку поставок JavaScript-пакетов. Использование синонимичного имени, подмена библиотеки с высоким доверием, предварительная публикация чистого пакета-приманки и массовое сканирование всей организации - все эти приёмы указывают на хорошо спланированную операцию, направленную на максимальное распространение вредоносного кода среди разработчиков AI-приложений. Учитывая критическую роль таких сред в современной корпоративной инфраструктуре, подобные атаки будут повторяться, и сообществу необходимо усиливать механизмы верификации публикуемых пакетов и автоматического контроля целостности зависимостей.
Индикаторы компрометации
IPv4 Port Combinations
- 23.254.164.123:443
URLs
- https://23.254.164.92:8000/update/49890878
Packages
- easy-day-js@1.11.22
- easy-day-js@1.11.21
Affected packages
- @mastra/acp 0.2.2
- @mastra/agent-browser 0.3.2
- @mastra/agent-builder 1.0.42
- @mastra/agentcore 0.2.2
- @mastra/agentfs 0.1.1
- @mastra/ai-sdk 1.4.6
- @mastra/arize 1.2.3
- @mastra/arthur 0.3.3
- @mastra/astra 1.0.2
- @mastra/auth 1.0.3
- @mastra/auth-auth0 1.0.2
- @mastra/auth-better-auth 1.0.4
- @mastra/auth-clerk 1.0.3
- @mastra/auth-cloud 1.1.4
- @mastra/auth-firebase 1.0.1
- @mastra/auth-okta 0.0.5
- @mastra/auth-studio 1.2.4
- @mastra/auth-supabase 1.0.2
- @mastra/auth-workos 1.5.3
- @mastra/azure 0.2.3
- @mastra/blaxel 0.4.2
- @mastra/braintrust 1.1.4
- @mastra/brightdata 0.2.2
- @mastra/browser-viewer 0.1.3
- @mastra/chroma 1.0.2
- @mastra/claude 1.0.3
- @mastra/clickhouse 1.10.1
- @mastra/client-js 1.24.1
- @mastra/cloudflare 1.4.2
- @mastra/cloudflare-d1 1.0.7
- @mastra/codemod 1.0.4
- @mastra/convex 1.2.2
- @mastra/core 1.42.1
- @mastra/couchbase 1.0.4
- @mastra/cursor 0.2.1
- @mastra/datadog 1.2.5
- @mastra/daytona 0.4.2
- @mastra/deployer 1.42.1
- @mastra/deployer-cloud 1.42.1
- @mastra/deployer-cloudflare 1.1.44
- @mastra/deployer-netlify 1.1.20
- @mastra/deployer-vercel 1.1.38
- @mastra/docker 0.3.1
- @mastra/dsql 1.0.3
- @mastra/duckdb 1.4.3
- @mastra/dynamodb 1.0.9
- @mastra/e2b 0.3.4
- @mastra/editor 0.11.3
- @mastra/elasticsearch 1.2.1
- @mastra/evals 1.3.1
- @mastra/express 1.3.31
- @mastra/fastembed 1.1.3
- @mastra/fastify 1.3.31
- @mastra/files-sdk 0.2.1
- @mastra/gcs 0.2.3
- @mastra/github-signals 0.1.2
- @mastra/google-cloud-pubsub 1.0.6
- @mastra/google-drive 0.1.1
- @mastra/hono 1.4.26
- @mastra/inngest 1.5.2
- @mastra/koa 1.5.14
- @mastra/laminar 1.2.3
- @mastra/lance 1.0.7
- @mastra/langfuse 1.3.6
- @mastra/langsmith 1.2.4
- @mastra/libsql 1.13.1
- @mastra/loggers 1.1.3
- @mastra/longmemeval 1.0.50
- @mastra/mcp 1.10.1
- @mastra/mcp-docs-server 1.1.47
- @mastra/mcp-registry-registry 1.0.2
- @mastra/memory 1.20.4
- @mastra/mongodb 1.9.3
- @mastra/mssql 1.3.2
- @mastra/mysql 0.1.1
- @mastra/nestjs 0.1.15
- @mastra/observability 1.14.2
- @mastra/openai 1.0.2
- @mastra/opencode 0.0.47
- @mastra/opensearch 1.0.3
- @mastra/otel-bridge 1.2.3
- @mastra/otel-exporter 1.2.3
- @mastra/perplexity 0.1.1
- @mastra/pg 1.13.1
- @mastra/pinecone 1.0.2
- @mastra/playground-ui 33.0.1
- @mastra/posthog 1.0.29
- @mastra/qdrant 1.0.3
- @mastra/rag 2.2.2
- @mastra/react 1.0.1
- @mastra/redis 1.1.3
- @mastra/redis-streams 0.0.4
- @mastra/s3 0.5.3
- @mastra/s3vectors 1.0.7
- @mastra/schema-compat 1.2.12
- @mastra/sentry 1.1.4
- @mastra/server 2.1.1
- @mastra/slack 1.3.1
- @mastra/spanner 1.1.2
- @mastra/stagehand 0.2.5
- @mastra/tavily 1.0.3
- @mastra/temporal 0.1.14
- @mastra/turbopuffer 1.0.3
- @mastra/twilio 1.0.2
- @mastra/upstash 1.1.3
- @mastra/vectorize 1.0.3
- @mastra/voice-aws-nova-sonic 0.1.4
- @mastra/voice-azure 0.11.2
- @mastra/voice-deepgram 0.12.2
- @mastra/voice-elevenlabs 0.12.2
- @mastra/voice-google 0.12.3
- @mastra/voice-google-gemini-live 0.12.2
- @mastra/voice-openai 0.12.3
- @mastra/voice-openai-realtime 0.12.6
- create-mastra 1.13.1
- mastra 1.13.1