
Когда пакет тебе выбирает нейронка
На прошлой неделе я попросил Claude Code добавить рендеринг markdown в проект. Через секунду в зависимостях появился flutter_markdown , нормальный пакет от flutter.dev . Я нажал accept. А потом случайно открыл его карточку, а там прямо в шапке:
This project has been discontinued, and will not receive further updates.
This project has been discontinued, and will not receive further updates.
Пакет уже больше года как мёртв, есть преемник: flutter_markdown_plus . Просто в обучающих данных агента он всё ещё живой.
Другой пример, ещё свежее. Скажешь Cursor «нужно поднять S3-совместимое хранилище для тестов», и он напишет docker-compose с minio/minio:latest . Только вот репозиторий minio/minio архивирован 25 апреля 2026 года , MinIO Inc. толкает всех в коммерческий AIStor ( подробнее ). SDK ещё обновляется, но сам сервер мёртв.
Оба факта проверяются за 30 секунд. Открыл карточку, посмотрел в шапку, увидел статус. Это даже не «надо разбираться». Это красная плашка, на которую не посмотрели. Потому что в чате с агентом ты не открываешь pub.dev. Ты нажимаешь accept.
А что насчёт живых пакетов?
С мёртвыми всё понятно. А если пакет живой, активный, миллион скачиваний?
Год назад я полтора дня дебажил неприятный баг. Flutter-приложение, авторизация через flutter_secure_storage . Де-факто стандарт хранения токенов в Keychain и Android Keystore. Активный мейнтейнер, миллионы скачиваний.
Симптом: часть пользователей iOS разлогинивает после обновления через App Store. Не всех. Не сразу. Иногда после нескольких часов в background. read() возвращает null , хотя write() отработал без ошибок. Я думал на сервер, на iOS API, на собственную инвалидацию токенов. Часов восемь ушло на перебор всех гипотез на своей стороне.
А когда я открыл GitHub Issues самого пакета, там был ад. #284 : «данные пропадают после обновления через App Store». #223 : «после 2+ часов в background». #524 : «массово на iOS 16.3+». Сотни комментариев, годами. Корневая причина: KeychainAccessibility применялся только при SecItemAdd , а на update и read не применялся. Починили в v9.1.0.
Мне повезло: патч уже был. Стартанул бы на полгода раньше, сидел бы и ждал, пока чужой человек починит чужой код.
Баги в чужом коде — не твоя зона. Что попадает в твой проект — твоя. Первое не контролируешь никак. Второе: это решение, которое всё чаще принимает не человек, а агент. За 200 миллисекунд. Без открытой карточки. Без чтения issues.
И вот в этот момент, когда последний человеческий фильтр исчезает, появляется отдельный класс атак, рассчитанный именно на него. Раньше они были маргинальной экзотикой: человек редко ошибается в имени знакомого пакета. Теперь, когда имя пакета вообще никто не читает, угроза получила собственное название.
Slopsquatting: атака, которая без ИИ не работала бы
Термин slopsquatting появился весной 2025-го по аналогии с typosquatting’ом. Только typosquatting рассчитан на человека, который опечатался при pip install . А slopsquatting на нейронку, которая опечаталась при генерации кода.
Логика: гоняешь LLM через тысячи запросов «напиши Python-скрипт, который делает X», собираешь имена пакетов, которые она импортирует. Часть существует, часть выдуманы. Регистрируешь выдуманные на PyPI с вредоносным setup.py . Ждёшь.
Главная работа здесь: «We Have a Package for You!» ( arXiv:2406.10279 , USENIX Security 2025). 576 000 примеров кода, 16 моделей:
19,7% рекомендованных пакетов не существуют. Каждый пятый.
19,7% рекомендованных пакетов не существуют. Каждый пятый.
У коммерческих моделей 5,2% , у open-source 21,7% . В четыре раза разница.
У коммерческих моделей 5,2% , у open-source 21,7% . В четыре раза разница.
58% галлюцинаций повторяются между запусками. Атакующему не нужно мониторить, достаточно собрать топ выдуманных имён.
58% галлюцинаций повторяются между запусками. Атакующему не нужно мониторить, достаточно собрать топ выдуманных имён.
В марте 2024 Bar Lanyado из Lasso Security сделал PoC: зарегистрировал на PyPI пустой пакет huggingface-cli , самое частое галлюцинируемое имя несуществующего Hugging Face CLI. За три месяца 30 000+ загрузок , в том числе у Hugging Face-owned репо и исследовательского проекта Alibaba. Пакет был пустой. Был бы атакующим, у него было бы 30 000 машин с произвольным кодом.
Честная оговорка: публично задокументированной атаки именно через slop-имя с реальным payload до сих пор нет . Это пока предсказуемая угроза, а не серия инцидентов. Не передёргивай.
Зато с supply chain в целом всё веселее. По отчёту Sonatype State of the Software Supply Chain 2026, в 2025-м в open-source реестрах нашли 454 648 новых вредоносных пакетов , 99% в npm. Из крупного:
ultralytics (PyPI, декабрь 2024): XMRig-майнер через GitHub Actions injection, пакет с 60 млн скачиваний.
ultralytics (PyPI, декабрь 2024): XMRig-майнер через GitHub Actions injection, пакет с 60 млн скачиваний.
@lottiefiles/lottie-player (октябрь 2024): фишинг мейнтейнера, crypto-drainer в браузере.
@lottiefiles/lottie-player (октябрь 2024): фишинг мейнтейнера, crypto-drainer в браузере.
eslint-config-prettier (июль 2025, CVE-2025-54313): фишинг с домена npnjs.com , скомпрометированы пакеты с 78 млн weekly downloads.
eslint-config-prettier (июль 2025, CVE-2025-54313): фишинг с домена npnjs.com , скомпрометированы пакеты с 78 млн weekly downloads.
Shai-Hulud (сентябрь 2025) → 2.0 (ноябрь 2025): первый self-replicating npm-червь, во второй волне 25 000+ malicious-репозиториев.
Shai-Hulud (сентябрь 2025) → 2.0 (ноябрь 2025): первый self-replicating npm-червь, во второй волне 25 000+ malicious-репозиториев.
chalk + debug (сентябрь 2025): фишинг Qix, скомпрометированы пакеты с 2 миллиардами weekly downloads . Крупнейший npm-инцидент в истории.
chalk + debug (сентябрь 2025): фишинг Qix, скомпрометированы пакеты с 2 миллиардами weekly downloads . Крупнейший npm-инцидент в истории.
Это всё происходило, пока ты смотрел в чат и нажимал accept.
Заброшенные пакеты: отдельная категория
Активный ≠ живой. Свежий релиз может оказаться бампом зависимостей бота, а мейнтейнер не отвечал на issues полгода. Проверка по четырём пунктам: last commit (не release, именно коммит), время ответа на последние пять issues, соотношение открытых к закрытым, есть ли SECURITY.md . Три из четырёх красные, ищем альтернативу.
Решение: skill, который заставляет агента проверять пакет
Решений тут вагон. Можно проверять руками. Можно pre-commit hook. Можно CI-сканер. Можно Socket / Snyk / phylum / osv-scanner. Можно Renovate с delay-окном. Всё работает, комбинация лучше.
Я не претендую на «правильный» ответ. Вы программисты, сами выберете удобное. Покажу один инструмент, который у меня стоит. Это skill для Claude Code . Дальше на ваше усмотрение.
Идея: не проверять пакеты руками, а заставить агента самого делать это до установки. У Claude Code для этого skills, у Cursor это rules. Формат разный, смысл один: markdown-файл, агент читает и следует инструкции.
Минимальный skill для Claude Code. Кладёшь в ~/.claude/skills/check-dep/SKILL.md глобально или в .claude/skills/check-dep/SKILL.md в репозитории:
Две вещи. Первое: не нажимаешь accept вслепую, агент сам приходит с отчётом. Второе: отчёт остаётся в истории, через полгода можно сделать аудит, кто одобрил.
В Cursor аналогичный файл лежит в .cursor/rules/check-dep.mdc . Синтаксис frontmatter чуть другой ( globs , alwaysApply ), смысл тот же.
Агент ставит в проект пакеты, которые ты не открывал. Баги внутри чужого кода ты не контролируешь, остаётся ждать патч. А за то, что попадает в package.json / pubspec.yaml / requirements.txt , отвечаешь ты.