Сорок раундов ИИ-ревью: как двойной аудит выявил скрытые уязвимости в коде
Habr AI · оригинал
Материал подготовлен автоматизированной редакционной системой. Факты можно сверить по указанному первоисточнику.

Разработчик проекта skillmem провел сорок итераций автоматизированного ревью с использованием двух разных LLM-моделей, чтобы закрыть критические ошибки безопасности. Процесс выявил, что каждый фикс часто порождал новые регрессии, а «чистый» код возможен только при пересечении результатов независимых аудиторов.
Ценность: Материал демонстрирует практический подход к повышению надежности кода с помощью ИИ: вместо единичной проверки используется итеративный процесс с жесткими критериями остановки, что позволяет находить сложные логические ошибки и уязвимости, которые упускаются при стандартном тестировании.
В недавнем релизе локального инструмента для памяти кодовых агентов skillmem (версия 0.11.0) разработчик описал процесс глубокого аудита кода, который занял сорок раундов. Инициатива возникла после того, как в предыдущей версии была закрыта одна известная уязвимость, однако автор решил не доверять единичной проверке и организовал «враждебное» ревью с участием двух независимых языковых моделей: одной на базе Claude и другой на стороне GPT. Каждая модель была обязана воспроизводить найденные проблемы конкретными командами, а не просто рассуждать о них. Критерием остановки процесса стало отсутствие воспроизводимых ошибок уровня P1 (потеря данных, нарушение доверия) и P2 в двух последовательных раундах.
Аудит разбился на три волны. Первая волна (раунды 1–18) выявила шесть критических уязвимостей (P1), которые находились не в очевидных местах, а в механизмах перехвата HTTP-запросов, записи публичных навыков и управлении правами доверия. Например, система могла выдавать токен доверия любому процессу или допускать path-traversal при экспорте данных. Вторая волна (раунды 19–23) сосредоточилась на процессе установки и миграции конфигураций. Здесь были обнаружены проблемы с дублированием хуков, перезаписью бэкапов из-за одинаковых временных меток и созданием файлов с небезопасными правами доступа рядом с OAuth-данными.
Наиболее интересные находки появились в третьей волне (раунды 24–40), когда модели анализировали ядро системы. Ревьюеры обнаружили, что HTTP-сервер при конфликтах версий мог раскрывать заголовки чужих приватных записей, а функции поиска и списков возвращали пустые ответы для собственных данных пользователя из-за некорректной работы фильтров видимости. Также была найдена уязвимость в импорте данных через символьные ссылки, позволявшая читать системные файлы вроде .zshrc. Особое внимание привлекла функция маскировки секретов (scrub), которая оказалась неидемпотентной: при повторном запуске она искала уже замаскированные строки, что приводило к бесконечному росту текста и снятию одобрений владельца.
Ключевым выводом автора стал эффект «каждый второй фикс рождал регрессию». Исправление одной ошибки в поисковом движке потребовало пяти итераций: сначала ограничили окно кандидатов, затем убрали лимиты, что привело к деградации производительности до 20 секунд на запрос, и только в финальной версии удалось оптимизировать выборку данных. Если бы процесс остановился после первого исправления, релиз вышел бы с серьезной утечкой памяти и медленной работой.
Разработчик подчеркивает важность использования двух разных моделей для ревью, так как их ошибки не совпадают полностью, а пересечение находок позволяет отфильтровать ложные срабатывания. Также отмечается необходимость строгого формата отчетов (уровень критичности, файл, строка, доказательство) и контроля за тем, чтобы ИИ-ревьюер не изменял код самостоятельно. В результате процесса количество тестов выросло со 221 до 350, а граница доверия была унифицирована для всех интерфейсов (HTTP, MCP, CLI). Оставшиеся мелкие проблемы (P3) перенесены в следующий релиз.