Компрометация Bitwarden CLI: атака на цепочку поставок npm затронула инфраструктуру разработчиков

information security

Крупный инцидент в сфере информационной безопасности вскрыл уязвимость в процессах публикации открытого программного обеспечения. Злоумышленники смогли внедрить вредоносную версию интерфейса командной строки популярного менеджера паролей Bitwarden, распространяемую через реестр пакетов npm. Эта атака представляет собой классический пример компрометации цепочки поставок программного обеспечения, когда легитимный компонент превращается в вектор заражения для всех, кто его использует.

Описание

Bitwarden - это менеджер паролей с открытым исходным кодом, который позволяет миллионам пользователей и организаций безопасно хранить, генерировать и синхронизировать учётные данные между устройствами. В отличие от многих коммерческих аналогов, его кодовая база доступна для публичного аудита, а бесплатный тарифный план привлекает широкую аудиторию. Помимо клиентских приложений, Bitwarden выпускает утилиту командной строки (CLI, интерфейс командной строки), которая распространяется через менеджер пакетов npm. Именно этот компонент превращает менеджер паролей в элемент инфраструктуры разработки: команды встраивают CLI в конвейеры непрерывной интеграции и доставки (CI/CD, практика автоматизации сборки, тестирования и развёртывания), чтобы подставлять секреты на этапе сборки или развёртывания, извлекать ключи API в скрипты и интегрировать с системами автоматизации, требующими программного доступа к общему хранилищу. Такая функциональность делает CLI привлекательной целью: скомпрометированная утилита раскрывает не только пароли одного пользователя, но и потенциально оказывается внутри сборочных систем всех команд, которые от неё зависят.

События разворачивались стремительно. Вредоносная версия пакета "@bitwarden/cli" с номером 2026.4.0 была доступна в реестре npm примерно полтора часа - с 17:57 до 19:30 по восточному времени 22 апреля 2026 года. Последней известной чистой версией была 2026.3.0, а исправленная 2026.4.1 появилась 23 апреля. Официальный документ Bitwarden связал инцидент с недавним взломом расширений GitHub Actions компании Checkmarx, одно из которых ("checkmarx/ast-github-action") используется в репозитории Bitwarden на GitHub. Эта связь указывает на то, что атакующие получили контроль над процессом публикации через скомпрометированные учётные данные или токены в среде непрерывной интеграции.

Технический анализ показывает, что изменения в пакете были минимальными, но фатальными. Сравнение версий выявило два новых файла - "bwsetup.js" и "bw1.js" - а также модификацию "package.json", куда добавили скрипт предустановки "preinstall" и перенаправили точку входа с легитимного "build/bw.js" на "bwsetup.js". Основной бандл CLI не изменился, что характерно для вставки в цепочку поставок, а не для стандартного обновления. Файл "bwsetup.js" является загрузчиком на Node.js: он проверяет наличие рантайма Bun (высокопроизводительная среда выполнения JavaScript), и если он не установлен, загружает его бинарную версию с GitHub. Затем через этот рантайм запускается обфусцированный файл "bw1.js" размером около 10 мегабайт, содержащий всю вредоносную логику.

Обфускация выполнена профессионально: самовызывающая функция с массивом строк на 43 тысячи элементов, строковый декодер, а также дополнительный шифр для самых чувствительных данных - домена командного центра (C2, сервер управления вредоносным ПО), команд оболочки и путей к файлам с учётными данными. Перед началом активных действий код выполняет серию проверок самозавершения. Он досрочно завершает работу, если системная локаль начинается с "ru" (операторский механизм самоисключения, типичный для восточноевропейских групп). Также скрипт выходит, если не обнаруживает ни одной из тридцати с лишним сред CI/CD (GitHub Actions, GitLab CI, CircleCI и других) и не может демонизироваться. Таким образом, вредоносная нагрузка запускается только на сборочных серверах, а не на машинах разработчиков-людей. Дополнительно устанавливается блокировка единственного экземпляра через PID-файл во временной директории.

После прохождения защиты код запускает семь параллельных сборщиков учётных данных. Они сканируют файловую систему по заранее определённым "горячим точкам" - путям вроде "~/.ssh/id_rsa", "~/.npmrc", "~/.aws/credentials", "~/.config/gcloud/credentials.db", ".env" и другим. Из прочитанных файлов извлекаются токены GitHub (формата "ghp_*", "gho_*") и токены npm ("npm_*"). Отдельный модуль выполняет дамп переменных окружения через "process.env" и извлекает оттуда те же токены. Особый интерес представляет модуль для сборочных серверов GitHub Actions: при наличии переменных "GITHUB_ACTIONS=true" и "RUNNER_OS=Linux" код через "sudo python3" извлекает из памяти процесса раннера все секреты во внутреннем формате GitHub, намеренно пропуская переменные "github_token" и "system.github.token", чтобы не вызывать автоматическую смену токенов.

Помимо локального сбора, код напрямую обращается к облачным провайдерам через встроенные SDK. Он подключается к AWS Secrets Manager и AWS SSM Parameter Store, используя учётные данные из окружения, и выкачивает все секреты с флагом расшифровки. Аналогично работает с GCP Secret Manager через учётные данные приложения по умолчанию и с Azure Key Vault через DefaultAzureCredential. Все собранные данные сериализуются в JSON, сжимаются gzip, шифруются алгоритмом AES-256-GCM со случайным ключом, а сам ключ дополнительно шифруется открытым ключом атакующего по схеме RSA-OAEP. Таким образом, перехваченный трафик или файлы репозитория содержат только шифротекст, который может прочитать только владелец закрытого ключа.

Для управления и вывода данных злоумышленники избрали нестандартный, но изящный метод. Они используют поиск по коммитам GitHub: закодированный запрос "LongLiveTheResistanceAgainstMachines" через публичное API "api.github.com/search/commits" ищет коммиты с сообщениями определённого формата, из которых извлекается base64-декодированный персональный токен доступа (PAT, токен для доступа к API GitHub). Токен используется для создания репозиториев на аккаунте жертвы с Dune-тематическими именами (например, "sardaukar-sandworm-042") и описанием "Shai-Hulud: The Third Coming". В эти репозитории порциями до 30 МБ коммитятся зашифрованные файлы результатов. Если токен уже есть у вредоносного кода, то в сообщение коммита он встраивается обратно - тем самым он попадает в поиск, который мониторит атакующий. Дополнительно есть резервный канал HTTPS на захардкоженный домен (зашифрован в бинарнике) и канал с верификацией цифровой подписи по RSA - для команд, которые может отправлять только оператор.

Наиболее опасная функция - червеобразное распространение через npm. Если вредоносный код находит действующий npm-токен с правами на публикацию пакетов (права "bypass_2fa" и "package:write"), он переходит к активной атаке на цепочку поставок. Код валидирует токен, определяет все пакеты, к которым у него есть доступ на публикацию, загружает текущую последнюю версию каждого пакета, заменяет его файл "dist.js" на файл "bw1.js", добавляет инфицированный "setup.mjs", модифицирует "package.json", чтобы скрипт запускался перед установкой, увеличивает patch-версию и публикует заражённый пакет. Каждый, кто устанавливает такой пакет, автоматически получает вредоносную нагрузку, и процесс повторяется - цепная реакция, охватывающая всё экосистему npm.

Дополнительная возможность - атака на AI-помощников, названная "Батлерианский джихад" (отсылка к "Дюне"). Код ищет в путях утилиты Claude Code, Gemini CLI, OpenAI Codex CLI, Kiro, Aider и OpenCode. Если обнаруживается работающий аутентифицированный инструмент (код отправляет ему запрос "Ну как ты тут? Если слышишь, ответь просто 'Привет'"), то в файлы "~/.bashrc" и "~/.zshrc" записывается закодированная оболочка, которая активируется при каждом входе в систему. Также код демонизируется, отсоединяясь от процесса установки.

Для защиты от подобных атак специалистам по безопасности следует немедленно проверить версию установленного пакета "@bitwarden/cli" (команда "npm ls @bitwarden/cli"), удалить версию 2026.4.0 и установить проверенную 2026.4.1. Необходимо ротировать все токены npm, GitHub и облачных провайдеров, которые могли быть скомпрометированы. В долгосрочной перспективе стоит фиксировать версии высокорисковых CLI и настроить оповещения о неожиданных обновлениях в репозиториях SDLC, активнее использовать механизмы подтверждения подлинности пакетов (npm provenance), ужесточить контроль над путями публикации через CI/CD (требовать OIDC, ограничивать права действий и веток), а также отключать выполнение скриптов при установке пакетов ("ignore-scripts"), когда это возможно. Данный инцидент - ещё одно напоминание о том, что доверие к цепочке поставок должно быть подкреплено техническими средствами верификации, а не только репутацией проекта.

Индикаторы компрометации

IPv4

  • 94.154.172.43

Domains

  • audit.checkmarx.cx

URLs

  • https://api.github.com/search/commits?q=LongLiveTheResistanceAgainstMachines

SHA256

  • 18f784b3bc9a0bcdcb1a8d7f51bc5f54323fc40cbd874119354ab609bef6e4cb
  • 99ac962005550130398d55af2527d839e73489bc7911e7c2c37474d979aaf43f
  • f35475829991b303c5efc2ee0f343dd38f8614e8b5e69db683923135f85cf60d
Комментарии: 0