Мы оцениваем каждую новую лидирующую модель по самому сложному критерию для нашего продукта по устранению уязвимостей: написание исправления безопасности, которому инженер доверится и которое он объединит с кодом. Наше основное наблюдение заключается в том, что выбор судьи сильнее влиял на наши оценки, чем выбор модели, а разница между ведущими моделями оказалась меньше нашей погрешности измерения. Эта публикация о том, как мы создали заслуживающую доверия систему оценки и как достоверные измерения изменили то, что мы можем улучшить.
Критические уязвимости устраняются быстрее, чем когда-либо. На платформе H1 среднее время устранения критических отчетов сократилось на 61% в период с июня 2024 года по июнь 2026 года. За тот же период количество открытых действительных отчетов по всем уровням критичности выросло на 131%, а количество открытых критических отчетов — на 123%. Рост скорости реален, но объемы опережают его. Теперь ценность сосредоточена на том, что происходит дальше: превращение подтвержденной находки в проверенное исправление, которое инженер проверяет, принимает и объединяет.
Именно поэтому организации уделяют больше внимания устранению уязвимостей в рамках непрерывного управления воздействием угроз (CTEM): найти уязвимость, подтвердить ее, найти первопричину, устранить ее, подтвердить эффективность исправления, повторить. Устранение уязвимостей — это этап, на котором риск действительно снижается, поэтому к нему мы предъявляем самые высокие требования.
Мы оцениваем лидирующие модели по этой шкале. В этой статье рассказывается о том, что контролируемое сравнение этих моделей говорит нам об устранении уязвимостей и как эти результаты совершенствуют наши инструментальные средства и оценочные фреймворки.
Вопросы, лежащие в основе оценки моделей: 1. Какая модель пишет лучшие исправления? 2. Какой вспомогательный каркас (harness) вокруг модели работает с ней лучше всего? 3. Можно ли измерить разницу достаточно последовательно и надежно, чтобы доверять результату?
Путь от первого вопроса к третьему — это то, где мы узнали больше всего и о чем мы расскажем здесь.
HackerOne не использует конфиденциальные материалы исследователей или данные о клиентских уязвимостях для обучения, тонкой настройки или иного улучшения генеративных моделей ИИ. Более подробную информацию можно найти в нашей документации по безопасности и доверию Hai и в нашем блоге «Ответственный ИИ в HackerOne».
Все начинается с обвязки (harness)
Модель — это лишь один из компонентов, а обвязка выступает в роли операционного слоя. Обвязка платформы H1 находится между лидирующей моделью кибер-ИИ и командой безопасности: она определяет границы того, к чему модель может прикасаться, проверяет найденное на наличие ложных срабатываний и связывает каждую подтвержденную находку с исправлением, с которым разработчик может работать. Другими словами, вспомогательная структура вокруг модели определяет большую часть того, что вы наблюдаете: как вы представляете находку, сколько шагов получает агент, что идет первым — анализ или исправление, и что происходит, когда он ничего не возвращает. Как показывает остальная часть этой статьи, мы запускаем наши обвязки на разных моделях, а затем совершенствуем сами обвязки, чтобы получить максимум пользы от каждой из них.
Рисунок 1. Обвязка представляет собой вспомогательную структуру вокруг модели: она принимает находку, выполняет анализ первопричин и выдает исправление, которое мы можем оценить. Мы прогоняем этот же конвейер через разные модели на одних и тех же примерах с одинаковой системой оценки, что позволяет нам с большей уверенностью относить изменение результатов к конкретному изменению в модели или обвязке.
Тестовые примеры определяют, какое именно сравнение проводится. Модели имеют тенденцию получать более высокие оценки на общедоступных бенчмарках и раскрытых уязвимостях с открытым исходным кодом, отчасти потому, что эти материалы хорошо представлены в их обучающих данных. Мы создали наш набор с учетом этого, опираясь на уязвимости, которые исправили наши собственные инженеры, а не на общедоступные бенчмарки. Набор охватывает более десяти классов уязвимостей, включая ошибки контроля доступа, IDOR, XSS, CSRF, внедрение кода, обход HTTP-запросов, исчерпание ресурсов, раскрытие информации и ошибки бизнес-логики. Уровни критичности варьируются от низкого до критического, и ни один отдельный класс не составляет более четверти набора. Каждая реальная уязвимость связана с патчем, который действительно выпустили наши инженеры HackerOne. Примерно 40% случаев вообще не содержат уязвимостей, поскольку каждое ложное срабатывание стоит команде безопасности времени: агент должен решить, является ли находка реальной, прежде чем решать, как ее исправить. Каждая модель оценивается по одному и тому же общему набору в общей сложности для более чем 1000 тестов.
Самостоятельное чтение патчей
Нашим первым шагом с каждой лидирующей моделью было чтение работы, а не слепое доверие оценке. Мы выбрали 20% выборку с акцентом на выбросы и случаи с самыми низкими оценками и прочитали патч каждой модели бок о бок с исправлением, отправленным нашими инженерами. Случаи охватывали как общие классы, такие как внедрение HTML, так и находки, требующие реальных знаний предметной области, такие как проверка авторизации в слое GraphQL.
То, что мы прочитали, не соответствовало тому, что показывали оценки. Во многих из рассмотренных нами случаев наши инженеры оценили исправления новейших лидирующих моделей как сопоставимые с отправленными нами патчами, а некоторые из них оказались более комплексными. Тем не менее, судьи ставили им более низкие оценки. Причина крылась в том, как распределялся вес при оценке. Судья уже учитывал несколько измерений, но сигналы локализации имели слишком большой вес в общей оценке. Патч получал награду за попадание в те же файлы и строки, что и исправление, написанное человеком, а правильное исправление, решавшее проблему в другом месте, наказывалось. Наши измерения были смещены в сторону патчей, похожих на одно эталонное исправление, а не оценивали в первую очередь то, была ли уязвимость действительно устранена.
Если действительно более слабое исправление могло получить низкую оценку по неправильной причине, то сравнения, построенные на этой оценке, были сомнительными, и работать нужно было над системой оценки, а не над моделью.
Совершенствование нашего подхода к оценке
Качественная оценка патча безопасности — это сложная научная задача сама по себе. У уязвимости часто бывает больше одного правильного исправления, и самые удобные способы измерения качества отражают суть меньше, чем кажется. Оценить «это было исправлено» гораздо проще, чем «это было исправлено правильно». Улучшение работы судьи означало работу на трех фронтах одновременно, и чтение патчей указало на все три.
Во-первых, что измеряет судья. Мы поставили перед собой задачу воспроизвести внутри судьи те рассуждения, которые наши инженеры использовали при чтении патчей вручную, и сделать это без чрезмерной подгонки под какой-либо один тестовый набор. Наша система оценки развивалась в рамках трех подходов, каждый из которых стал ответом на измеренное ограничение предыдущего.
Рисунок 2. Три подхода к оценке, каждый из которых является осознанным ответом на измеренное ограничение предыдущего. Перекрытие является точным, но засчитывает только исправления, которые попадают туда же, куда и исправления наших инженеров, занижая количество правильно расположенных исправлений в других местах. Единый судья, который задает вопрос «выпустили бы мы это в продакшен?», распознает качество, которое пропускает перекрытие, но его оценка варьируется от запуска к запуску примерно так же, как модели отличаются друг от друга. Декомпозиция вопроса на девять независимых проверок, каждая из которых запускается несколько раз, дает стабильное измерение, достаточно точное для обнаружения тех различий, о которых мы сообщаем.
Суть улучшения заключалась в том, чтобы разбить один общий вопрос на девять конкретных. Два из них являются жесткими барьерами: если патч не применяется или уязвимость все еще воспроизводится, оценка равна нулю, независимо от того, насколько аккуратно выглядит код. Остальные семь отражают вопросы, с которыми реально работает рецензент:
- Устраняет ли он первопричину или лишь блокирует конкретный пример из отчета?
- Охватывает ли он также другие места в коде с тем же изъяном?
- Является ли исправление надежным, или злоумышленник может его обойти?
- Избегает ли он блокирования нормального, легитимного использования?
- Соответствует ли он соглашениям кодовой базы, в которой находится?
- Может ли он пройти экспертную оценку другого инженера?
- Безопасно ли его использовать без возникновения регрессии?
Ни один из этих пунктов не совпадает с местом расположения созданного человеком патча. Они задают вопрос о том, устранена ли уязвимость и является ли исправление надежным, что как раз и показывали выборочные проверки: старой оценке совпадений этого не хватало. В качестве бонуса декомпозиция носит диагностический характер: одно число говорит о том, что модель справилась плохо, а девять отдельных ответов показывают, как именно, и сам уровень расхождений по этим девяти пунктам несет в себе полезную информацию.
Рисунок 3. Несогласованность судей сильно варьируется в зависимости от вопроса. Вопрос «Перестала ли уязвимость воспроизводиться?» близок к детерминированному, в то время как вопрос «подлежит ли это чистой проверке?» имеет наибольшую дисперсию. Понимание того, какие проверки стабильны, а какие зашумлены, подсказывает нам, где повторные запуски оправдывают себя, а где оценка единственного судьи была бы наименее надежной.
Во-вторых, кто именно выступает в роли судьи. Чтение результатов выборочных проверок выявило предвзятость, свойственную самим моделям-судьям. Когда оценку выставляет модель, кто оценивает самого судью? Один судья создает конфликт интересов, поскольку некоторые тестируемые модели принадлежат к тому же семейству, что и оценивающий их судья, и мы напрямую наблюдали это в собственных данных: судья оценивал патч своего семейства более снисходительно, чем эквивалентный патч из другого семейства. Поэтому мы проводим оценку с помощью панели из шести судьей из разных семейств, ни одна модель никогда не оценивает представителя своего собственного семейства, и мы берем медиану вместо среднего, чтобы панель никогда не была более уверена, чем судьи внутри нее. Мы также проверяем, являются ли судьи действительно независимыми, поскольку добавление судей помогает только в том случае, если они совершают разные ошибки; наиболее ценными являются те пары, которые меньше всего согласны друг с другом.
В-третьих, насколько стабильно отдельное чтение. Повторный запуск того же судьи для того же патча не всегда давал тот же результат. Поэтому мы запускаем каждую проверку трижды для каждого патча и разрешаем спор большинством голосов — это стандартный способ уменьшить дисперсию между запусками, присущую оценке на основе моделей. Это не формальность: среди тысяч выборочных проверок примерно каждая восьмая давала разделение голосов по итогам трех запусков. Оценка проверки только один раз привела бы к тому, что значительная доля результатов определялась бы этой дисперсией, а не самим патчем.
Рисунок 4. Тот же набор патчей, оцененный шестью судьями. Разброс между самым требовательным и самым снисходительным судьей, составляющий примерно двукратную разницу на одной и той же работе, шире, чем разброс между лучшей и худшей моделью в сравнении. Другими словами, выбор судьи влияет на итоговую оценку больше, чем выбор модели. Это главный аргумент в пользу панели с консенсусом по медиане: любая таблица лидеров с одним судьей отражает калибровку этого судьи в такой же степени, как и ранжируемые ею модели.
На идентичных патчах выбор судьи менял оценку сильнее, чем выбор модели. Именно поэтому мы проводим оценку с помощью панели, выполняем ее в трех экземплярах и запрещаем модели оценивать собственное семейство.
На идентичных патчах выбор судьи менял оценку сильнее, чем выбор модели. Именно поэтому мы проводим оценку с помощью панели, выполняем ее в трех экземплярах и запрещаем модели оценивать собственное семейство.
Что позволило нам обнаружить надежного судью
Получив наконец судью, которому мы могли доверять, мы перепроанализировали результаты, и перед нами открылась новая возможность. В одном из сравнений мощная передовая модель не уступала более ранней модели только в написании патчей, несмотря на явное превосходство в анализе первопричин на тех же кейсах и в той же конфигурации. Лучшее понимание уязвимостей при отсутствии лучших патчей — это сигнал, который стоит исследовать, и декомпозированная оценка позволила нам сделать именно это: поскольку девять проверок отделяют «создание слабого патча» от «полного отсутствия патча», причину удалось быстро локализовать.
В тех случаях, когда модель заранее подтверждала уязвимость, она в значительной части случаев возвращала пустой патч. Это не были сбои понимания: каждый случай сопровождался полным письменным объяснением исправления, подхода, шагов и проверочных тестов. Чего не хватало, так это самого кода в применимом виде. Две причины, и ни одна из них не является ограничением модели. Бюджет шагов был распределен неравномерно: его было много для анализа и мало для написания патча, поэтому модель, которая проводит тщательное исследование, могла исчерпать свой бюджет на поиск правильного кода еще до того, как что-либо написать. Кроме того, передача данных между этапами происходила с потерями: проза передавалась дальше, а ссылки на код отбрасывались, из-за чего этап создания патча был вынужден заново искать код, который собственный конвейер уже нашел.
Мы устранили обе проблемы и выпустили результат в виде специализированной обвязки (harness), сохранив при этом предыдущую в исходном виде, чтобы прежние сравнения оставались валидными. Этот урок применим шире: чтобы получить максимум от модели, нужно настраивать обвязку и окружающие ее ресурсы, а точная оценка — это то, что превращает странно выглядящую цифру в конкретную, устранимую причину. Разные модели требуют разного инструментария.
Самосовершенствующаяся обвязка
Ручная настройка обвязки для каждой модели не масштабируется, поэтому мы создали обвязку, которая автоматически улучшает собственные промпты. Она использует опубликованные обвязки для этих моделей в качестве основы, берет наши существующие оценки за базовую линию, предлагает и тестирует множество вариантов промптов, принимая изменения только тогда, когда данные доказывают, что улучшение сохраняется в масштабе, а не на каком-то удачном фрагменте.
Порядок операций имеет значение. Ранее мы пробовали реализовать похожий цикл для оригинальной оценки с весами совпадений, и он принес мало пользы, поскольку сигнал, который он оптимизировал, формировался теми же проблемами измерения, которые выявила проверка патчей. Как только усовершенствованный судья занял свое место — декомпозированный, учитывающий семейства и запускаемый трижды, — автоматическое улучшение промптов дало реальные, воспроизводимые результаты.
Кроме того, оптимизатор никогда не видел те результаты, по которым его оценивали. Мы разделили кейсы на набор для настройки, по которому итерируется цикл, и отложенный набор, которого он никогда не касается, и изменение промпта принимается только в том случае, если прирост наблюдается на отложенном наборе. Без такого разделения подобный цикл выучит тестовый набор, а не саму задачу.
Рисунок 5. Автоматическое улучшение промптов сдвинуло каждое оцениваемое измерение в правильном направлении на отложенных результатах, в то время как проверка жестких границ сохранялась на протяжении всего времени, поэтому ни один прирост не был достигнут за счет безопасности. Подчеркнуть стоит не размер прироста, а его зависимость от оценщика: он стал измеримым только тогда, когда оценка стала достаточно стабильной, чтобы его увидеть. При более зашумленной оценке тот же цикл оптимизировался бы под собственный шум.
Наиболее очевидный прирост наблюдался в полноте. По оценке нового судьи, самообучающаяся обвязка выдавала пригодное к использованию исправление для гораздо большего числа результатов, чем раньше, включая случаи, когда ранее она не возвращала ничего, в то время как точность оставалась стабильной практически без каких-либо потерь. Это результат, который первый, более слабый судья никогда не смог бы обеспечить. Он гонялся бы за собственным шумом и сообщал об улучшениях, которых не существовало.
Рисунок 6. Полнота и качество — это отдельные метрики, и наша система оценки отслеживает их раздельно. Итерации над обвязкой привели к резкому росту полноты — доли результатов, для которых агент вообще выдает патч. Качество (то, готов ли патч к отправке в продакшен) улучшается само по себе, более медленными темпами. Измерение обоих показателей позволяет нам точно направлять усилия, а не оптимизировать один за счет другого.
Хороший судья делает больше, чем просто честно ранжирует модели и отделяет «созданный патч» от «устраненной уязвимости», поэтому рост полноты не может замаскировать падение точности. Это фундамент, на котором держится обвязка для постоянного совершенствования. Без измерения, более точного, чем эффект, за которым вы гонитесь, самообучающаяся система оптимизируется под собственный шум; с точным измерением — она прогрессирует по нарастающей.
Применение передового ИИ для устранения уязвимостей
H1 Remediation разрабатывается на основе постоянных исследований, подкрепленных данными. Оценка передовых моделей заставила нас пересмотреть саму систему оценки. Модели были настолько хороши, что наша старая система подсчета баллов наказывала их за лучшие результаты, поэтому мы перестроили судью, прежде чем доверять какому-либо сравнению. Вот как этот цикл замыкается на практике: на входе — проверенная уязвимость, на выходе — проверенное исправление, подтвержденное, а не предполагаемое. Каждая модель оценивается по одному и тому же набору результатов одной и той же комиссией и по тем же критериям, поэтому рейтинг отражает исправления в пределах нашей погрешности измерений.
Ведущие передовые модели плотно группируются по качеству устранения уязвимостей, разделенные расстоянием, меньшим, чем погрешность измерения, поэтому крупные межпоколенческие разрывы, заметные в публичных таблицах лидеров по программированию, не проявляются на более сложной и ровной задаче написания патча, который одобрит специалист по безопасности. И в целом дизайн оценки повлиял на заявленный результат сильнее, чем выбор модели, поэтому именно судья, а не какая-либо модель, является инструментом, за которым мы следим наиболее тщательно.
Оценка каждого нового передового релиза по мере его появления является постоянной частью нашей работы, и это позволяет нашим обвязкам и системе оценки опережать модели, которые совершенствуются быстрее, чем тесты, созданные для их измерения. Все это в совокупности обеспечивает качество продукта. Наша оценка задает вопросы, которые задает инженер: применяется ли патч корректно, перестает ли уязвимость воспроизводиться и позволяет ли исправление избежать регрессий. H1 Remediation создана и протестирована в соответствии с этим стандартом. И поскольку мы проводим эту оценку для каждого нового передового релиза, H1 Remediation спроектирована так, чтобы совершенствоваться по мере развития моделей, поэтому клиентам не нужно запускать собственные сравнения.
Ограничения. Эти результаты получены на внутреннем бенчмарке и могут не переноситься на другие кодовые базы, обвязки или версии моделей. Они публикуются исключительно в информационных целях. Они не являются гарантией того, как поведет себя та или иная модель или продукт HackerOne, и не заменяют инженерную проверку исправления до его слияния. Названия продуктов и компаний являются товарными знаками соответствующих владельцев, используются только для идентификации протестированных продуктов и не подразумевают одобрения или аффилированности.












