Суть
Обычная цепочка поставки — про уязвимости в коде и зависимостях. В AI к ней добавляются сущности, которые кодом не являются и потому обычными средствами не проверяются: веса моделей, LoRA-адаптеры, обучающие и оценочные наборы, результаты слияния и преобразования форматов. Ошибка на любом звене приходит в прод как поведение модели, а не как падение сборки.
Почему проверить артефакт трудно
Смена формата сериализации помогает, но не решает. Уход от Python-pickle, исполняющего произвольный код при загрузке, снимает самый грубый вектор. Но бэкдор может быть встроен прямо в вычислительный граф и пережить перенос в формат, который принято считать безопасным, — например ONNX. Отдельно существует риск разбора: специально собранный файл модели эксплуатирует ошибку памяти в парсере формата, как переполнение кучи в разборе GGUF у llama.cpp (CVE-2024-23496).
Отсюда практическое следствие: статический анализ не устанавливает безопасность поведения. Приёмка модели — это прогон поведенческого набора тестов перед переводом в любую непроизводственную среду, а не только сканирование файла.
Провенанс: карточка модели ничего не доказывает
Model Card описывает модель, но не подтверждает её происхождение. Скомпрометированный или похожий по названию аккаунт поставщика публикует вредоносную модель под доверенным именем, и по метаданным это не отличить.
Пока модели, адаптеры, наборы данных, дообученные чекпоинты и результаты конвертации не подписаны и не закреплены хешем, их можно подменить — в передаче, в хранилище и особенно на границе продвижения, где автоматический конвейер принимает артефакт в доверенную среду.
Самая частая техническая причина — подвижная ссылка. Конвейер, разрешающий артефакт по тегу вроде latest, получает не то, что проверяли: между проверкой и использованием содержимое за тем же именем изменилось. Закрепление идёт по неизменяемому идентификатору содержимого, а не по имени версии.
Адаптеры и преобразования — отдельная поверхность
LoRA-адаптеры делают дообучение модульным, и ровно поэтому вредоносный адаптер компрометирует целостность базовой модели: и в средах совместного слияния, и на платформах инференса, которые скачивают адаптер и применяют его к уже развёрнутой модели.
Сервисы конвертации и слияния вносят изменения в момент преобразования, минуя ревью: проверяли одно, развернули результат преобразования.
Квантизация — не только оптимизация, но и точка атаки. Веса можно подобрать так, чтобы полноточная модель вела себя безобидно, а квантованный артефакт демонстрировал выбранное атакующим поведение (Egashira et al., 2025). Практическое следствие жёсткое: гарантии, полученные на полной точности, на развёрнутый квантованный артефакт не переносятся — проверять надо то, что поедет в прод (Quantization).
Slopsquatting — вектор, которого до ассистентов не было
Ассистенты-программисты массово выдумывают правдоподобные, но несуществующие имена пакетов. Атакующие регистрируют такие имена заранее, и предложенная ассистентом зависимость, поставленная без проверки, разрешается во вредоносный код.
Механика важна тем, что обходит привычную защиту: разработчик не ищет пакет сам и не сверяет его с экосистемой — имя пришло от инструмента, которому он доверяет. Проверка простая и дешёвая: существовал ли пакет до того, как его предложили, и кто его сопровождает.
Агентная половина: MCP-серверы и реестры инструментов
Для агента цепочка поставки продолжается в инструментах. Подключённый MCP-сервер — это чужой код с доступом к периметру, и относиться к нему надо как к зависимости, а не как к настройке (MCP, Tool Hijacking):
- компоненты берутся только из доверенных источников и проверяются криптографически;
- список разрешённых серверов — явный перечень, а не «что подключили, то и работает»;
- локально запускаемый сервер идёт в песочницу с урезанным доступом к файловой системе, сети и системным вызовам (Agent Sandboxing).
Масштаб проблемы измерен: на 3 984 опубликованных навыках доля дефектов составила 36%, у 76 нашлась активная вредоносная нагрузка (Tool Hijacking).
Импортированная инструкция — тоже зависимость
Умение, скачанное из чужого репозитория, — это текст, напрямую управляющий поведением агента, и обновляется он без единой строки диффа в твоём проекте. Отказ поэтому получается тише, чем у обычной зависимости: там хотя бы виден новый номер версии в манифесте.
Форма, которая это закрывает, повторяет обычный лок-файл:
- на каждое импортированное умение — источник, путь внутри источника и хеш содержимого; изменился текст наверху — изменился хеш, и это видно;
- установленное сверяется с локом после установки, а не только перед: иначе «поставилось» и «поставилось то самое» — разные утверждения, а выглядят одинаково;
- место установки ровно одно. Одно и то же умение в проектном и в глобальном каталоге даёт две расходящиеся копии, и какая из них сработает, решает порядок разрешения имён, а не автор. Установщик обязан на это падать, а не выбирать;
- глобальная установка помнит, каким локом она закреплена, и не переписывается молча из другого проекта с другим локом.
Отдельно стоит отметить обход этого класса конструкцией: если проектный каталог умений симлинкован в глобальный, двух копий физически не существует и расходиться нечему. Это дешевле лока и работает, пока источник один и он твой; для умений, приходящих извне, нужен именно лок с хешем.
Вторая задача того же слоя — раскладка, и она ортогональна версии. Умения, описания субагентов и подключения MCP-серверов каждый агент принимает в своём формате и в своих каталогах. Проект, который не может диктовать участникам, каким агентом пользоваться, — открытый репозиторий, команда со свободой выбора, — упирается в это раньше, чем в дрейф версий.
Форма, которая это закрывает: обвязка описывается одним манифестом зависимостей — какие умения, какие серверы, какие субагенты, — а разворачивание под конкретного агента делает установщик, потому что знание о раскладке принадлежит ему, а не проекту. Участник говорит «поставь под мой агент» и продолжает работать привычным инструментом.
Полезно видеть, что две задачи разные: лок отвечает на вопрос «тот ли текст», манифест — на вопрос «куда его положить». Одно без другого не работает: закреплённое по хешу умение, разложенное не туда, просто не подхватится, и молча.
Канал раздачи сам исполняет код
Форма «один манифест, раскладку делает установщик» теперь подтверждена не только докладом, но и кодом: открытый раздатчик конфигурации агентов из одного командного репозитория раскладывает умения, правила, субагентов, хуки, серверы инструментов и переменные окружения в родные каталоги примерно пятнадцати кодовых агентов, а отдельная команда сверяет, что разложенное действительно легло.
Тот же пример показывает, чего рассуждение выше не охватывает. Лок и манифест рассуждают об умении как о тексте: тот ли текст и куда его положить. Канал, который раздаёт текст, на практике раздаёт и исполняемое — и вопрос тогда уже не «что прочитает агент», а «что выполнится на машине человека». В разобранном случае таких путей четыре, и все включены по умолчанию:
- скрипт после синхронизации, объявленный в командном репозитории, запускается в конце каждого обновления — включая тихое обновление при старте сессии агента. Он получает всё окружение участника, включая токены, и по построению переживает сессию. Единственная защита — путь к скрипту не выходит за пределы клона;
- командные хуки — произвольные команды оболочки — и серверы инструментов применяются автоматически; пустой перечень разрешённых команд и хостов означает «без ограничений»;
- командные переменные окружения вписываются в профиль оболочки участника;
- самообновление срабатывает на завершении каждой сессии и ставит голое имя пакета, то есть то, что в этот момент лежит под подвижной меткой, — хотя проверка обновления за мгновение до этого знала номер версии. Это ровно та подвижная ссылка, о которой раздел «Провенанс» выше.
Пятый путь того же канала — уже не код, а инструкции: командный фрагмент вставляется между маркерами прямо в корневой файл инструкций каждого установленного агента, с пометкой «не редактировать, раздел управляется автоматически»; рядом так же вставляются блок командной «культуры» и правила поиска по урокам. Это самая дорогая поверхность из всех — постоянно загружаемая (Agent Instruction Surfaces), — и в неё пишет не владелец файла.
Писать в командный репозиторий при этом обязан каждый участник. Значит, канал исполнения открыт на запись всей команде, и одна скомпрометированная учётка — это код на машинах всех.
Главное в этом случае — где лежит выключатель. Автоприменение хуков и серверов инструментов читается из командного конфига, то есть из того же репозитория, содержимое которого оно должно пропускать или задерживать. У участника есть только аварийная переменная окружения для хуков; для скрипта после синхронизации и для серверов инструментов её нет вовсе. Авторы сами называют выключенное состояние «явным согласием» — то есть умолчание, по их же словам, обходится без него.
Отсюда формулировка, которую стоит держать как правило: выключатель согласия, лежащий в том же репозитории, что и то, на что даётся согласие, согласием не является. Это решение того, кто пишет в канал, а не того, на чьей машине он исполняется. Класс тот же, что у файлов инструкций в анализируемом дереве: доверие задаётся тем, кто положил, а не местом, где лежит (Instruction Hierarchy).
Что закрыто стандартом, а что нет. Для серверов инструментов есть AISVS C10.1 — доверенный источник, перечень разрешённых, песочница, — и умолчание «пустой перечень означает без ограничений» ему прямо противоречит. Хуки, скрипт после синхронизации, профиль оболочки и самообновление не покрыты ни C10, ни C6 — последний касается артефактов моделей: весов, наборов данных, адаптеров и их описи. Поэтому пункт чеклиста здесь свой.
Минимальная форма, которая это закрывает: согласие хранится у участника — в локальном конфиге, с умолчанием «спросить»; исполняемое из канала проходит тот же порядок изменения, что обычный код, — ревью и закрепление версии; самообновление ставит тот номер, который проверила проверка, а не метку.
Патчинг зависимостей перестал быть фоновой задачей
Цепочка поставки ускорилась с обеих сторон одновременно, и обе половины усиливают друг друга.
Кода стало больше, а уязвимости растут вместе с ним. Связь объёма кода с числом дефектов безопасности известна и до агентов; порядок величины, который называют для тщательно проверяемого криптографического кода, — единицы уязвимостей на тысячу строк. Агентная разработка увеличивает поток кода, и вместе с ним — поток уязвимостей, причём в чужих зависимостях тоже, потому что их пишут так же.
Модели научились находить и подтверждать уязвимости. Существенно здесь не обнаружение, а подтверждение эксплуатацией: замеры на наборах реальных уязвимостей просят модель не указать на подозрительное место, а написать работающий код эксплуатации, и доля успеха за два года выросла до величин, при которых это перестало быть исследовательским упражнением. Следствие двустороннее: то же умение доступно и защищающимся, и атакующим, но у атакующих нет обязанности разбирать ложные срабатывания.
Отсюда практический вывод, который стоит записать прямо: регулярный патчинг зависимостей из необязательной гигиены превратился в обязательную рутину, и делать его руками с той же частотой невозможно. Наблюдаемая автоматизация устроена так: ночной прогон читает ленту уязвимостей платформы, сверяет её с деревом зависимостей проекта, и там, где совпадение настоящее, сам открывает запрос на слияние с обновлением версии и описывает, чем проверял. Человек утром смотрит на готовое изменение и сливает.
Форма здесь важнее самого приёма: агент делает объёмную часть — сверку ленты с деревом и черновик изменения, — а решение остаётся за человеком, потому что цена ложного обновления версии на длинной ветке выше, чем цена его прочтения.
AI BOM: состав, который можно проверить машиной
Аналог SBOM для AI-артефакта: версионируемый машиночитаемый перечень наборов данных, весов, лицензий и заявлений о происхождении данных. Смысл появляется при двух условиях — перечень подписан до развёртывания, и сборка падает, если метаданные компонента отсутствуют. Неполный перечень, не влияющий на сборку, работает документацией, а не контролем.
Юридическая часть, которую забывают
Лицензии моделей и наборов данных предъявляют разные требования к использованию, распространению и коммерциализации. Отдельный риск — условия оператора модели: неясные правила обработки означают, что данные приложения могут попасть в обучение и всплыть позже, плюс возможные претензии по авторскому праву на материал, предоставленный поставщиком.
Связано с
- Trusted Artifacts — признаки артефакта, которому разрешено ехать в прод
- Tool Hijacking — инструменты и навыки как звено цепочки, с измеренной долей дефектов
- Quantization — преобразование как точка атаки, а не только экономия памяти
- MCP — чужой сервер в периметре агента
- Agent Sandboxing — куда помещать локально запускаемый компонент
- Abliteration — что можно сделать с моделью, получив к ней доступ
- MLOps Pipeline — где в конвейере стоит граница продвижения