Python-разработчик Роман Иманкулов едва не запустил бэкдор, который маскировался под обычный тестовый код и срабатывал уже на этапе установки зависимостей. История неприятно показательная: атака через npm install больше не выглядит экзотикой для security-конференций, а превращается в бытовой риск для любого инженера, который открыл «тестовое задание» от слишком настойчивого рекрутера.
Схема была простой и потому опасной, сообщает The Register. Через LinkedIn с Иманкуловым связалась женщина, представившаяся рекрутером небольшого криптостартапа. Она попросила посмотреть proof-of-concept-репозиторий с якобы сломанным кодом и проблемой вокруг устаревшего Node-модуля. По словам разработчика, запрос выглядел правдоподобно, но что-то в переписке не сходилось. Вместо того чтобы проверять репозиторий на рабочей машине, он поднял отдельный VPS у Hetzner, клонировал код туда и запустил локального ИИ-агента Pi на базе Codex в режиме read-only.
Дальше произошло то, что обычно любят обещать в презентациях, но редко показывают на живом кейсе. Агент почти сразу посоветовал не запускать код вообще. Он нашел подозрительный файл app/test/index.js: внешне тот выглядел как типичный неряшливый тестовый набор, но внутри был спрятан URL сервера, разбитый на фрагменты, чтобы не бросаться в глаза, и сетевой запрос, который мог выполнить все, что вернул бы удаленный сервер. Иманкулов признал, что сам пролистал тот же файл и не увидел проблемы. На глаз это был просто плохой JavaScript, а не ловушка.
Критический момент в том, что злоумышленнику даже не требовалось уговаривать жертву запускать какой-то бинарник или вручную исполнять сомнительный скрипт. Хватило бы привычного npm install. В package.json, как выяснилось, был прописан post-install hook prepare, который автоматически запускал вредоносный сценарий после установки. Для атакующего это почти идеальная механика: разработчики запускают установку зависимостей на автопилоте, а значит, атака через npm install прекрасно встраивается в рутинный workflow и не выглядит как красный флаг до последней секунды.
Независимый архитектор по open source и безопасности Девашри Датта в комментарии изданию объяснила, почему эта техника до сих пор работает. Во-первых, злоумышленники прячут выполнение кода не в «экзотике», а в стандартном жизненном цикле пакета. Во-вторых, обфускация здесь примитивная, но достаточная: домен собирается из мелких констант, поэтому статические проверки, которые ищут явные индикаторы компрометации, могут его пропустить. Это не новая техника, но именно поэтому она и эффективна. У инженеров выработан рефлекс доверять знакомым командам, а не подозревать их.
Есть и социальная часть атаки, не менее важная, чем package.json. По словам Иманкулова, коммиты в репозитории выглядели так, будто их делал разработчик с реальным следом в интернете. Но когда он связался с предполагаемым автором, тот ответил, что его уже не раз выдавали за себя на GitHub и этот код он не писал. Профиль рекрутера в LinkedIn, судя по описанию, тоже опирался на личность реальной журналистки, только аккаунт, вероятно, был поддельным. Показательно и то, что техническая осведомленность собеседницы не совпадала с ее профессиональным бэкграундом. Иными словами, перед нами не просто вредоносный репозиторий, а аккуратно собранная supply chain-атака с элементами социальной инженерии.
Контекст у истории тоже неприятный. LinkedIn регулярно рассказывает о миллионах фейковых аккаунтов, которые платформа удаляет до контакта с пользователями, но этого уже недостаточно, чтобы успокаивать инженеров. По данным компании, только с января по июнь 2025 года после жалоб пользователей были ограничены 386 тыс. аккаунтов. Для сравнения: в предыдущем полугодии таких было 266 тыс., а в первом полугодии 2021 года — 86 тыс. Рост выглядит слишком ровным, чтобы списать его на статистический шум. На этом фоне сообщения о «собеседованиях», «тестовых заданиях» и «помощи с proof-of-concept» становятся частью атакующего инструментария, а не просто странными историями из соцсетей.
Для бизнеса мораль еще жестче, чем для отдельного разработчика. Если заражение происходит на машине инженера до того, как код вообще попал в корпоративный контур, злоумышленник получает шанс добраться до SSH-ключей, токенов облачных провайдеров и внутренних репозиториев. То есть perimeter security можно строить сколько угодно, но если проверка чужого репо проходит на ноутбуке тимлида в обычной рабочей сессии, периметр уже давно остался позади. Отсюда практический вывод: тестовые задания, сторонние PoC и неизвестные репозитории нужно гонять либо в изолированных контейнерах, либо в защищенных cloud workstations, либо хотя бы на одноразовых sandbox-машинах без доступа к рабочим секретам.
Хорошая новость в том, что экосистема npm, похоже, наконец-то начала лечить самый очевидный класс проблем. GitHub готовит npm 12, где allowScripts по умолчанию будет выключен: npm install перестанет автоматически исполнять preinstall, install и postinstall-скрипты из зависимостей, если проект явно этого не разрешил. Менеджер продукта GitHub Лео Балтер прямо назвал install-time scripts крупнейшей поверхностью для выполнения кода в экосистеме npm. Иманкулов, впрочем, уже сделал свой вывод по-своему прагматично: просто перешел на pnpm, чтобы не исполнять такие сценарии по умолчанию. Вопрос теперь не в том, будут ли подобные атаки повторяться, а в том, как быстро команды перестанут считать «npm install на всякий случай» безобидной привычкой. Первоисточник с деталями кейса — .