Генерируйте и молитесь: использование SALLMS для оценки безопасности сгенерированного кода LLM: наша платформа: SALLM
9 февраля 2024 г.:::информация Этот документ доступен на arxiv под лицензией CC 4.0.
Авторы:
(1) Мохаммед Латиф Сиддик, факультет компьютерных наук и инженерии, Университет Нотр-Дам, Нотр-Дам;
(2) Джоанна К.С. Сантос, факультет компьютерных наук и инженерии, Университет Нотр-Дам, Нотр-Дам.
:::
Таблица ссылок
- Абстрактное и amp; Введение
- Предыстория и мотивация
- Наша структура: SALLM
- Эксперименты
- Результаты
- Ограничения и угрозы действительности
- Связанные работы
- Выводы и amp; Ссылки
3 Наша концепция: SALLM
Рис. 2 показан обзор нашей структуры и того, как она была создана. Наша структура состоит из трех основных компонентов: набора данных с подсказками, среды оценки для выполнения кода, настраиваемых методов оценки и новых показателей оценки. Каждый из этих компонентов более подробно описан в следующих подразделах.
3.1 Набор подсказок
Чтобы создать эффективную систему сравнительного анализа безопасности, нам сначала понадобился высококачественный набор подсказок. Хотя доступны два набора данных (LLMSecEval и SecurityEval) [63, 67], они имеют множество проблем. Во-первых, один из них (LLMSecEval [67]) представляет собой набор данных подсказок на естественном языке, формат которого поддерживают не все кодовые LLM. Во-вторых, SecurityEval имеет несколько подсказок, которые не выполняются, и в них отсутствуют тестовые примеры для проверки как его функциональной корректности, так и наличия уязвимостей в сгенерированном коде. Поэтому мы стремились создать вручную тщательно подобранный набор высококачественных подсказок, отвечающий нашим потребностям.
Создание набора данных подсказок платформы включало два этапа. Сначала мы получили фрагменты кода и тексты из разных источников. Затем мы вручную создали приглашение на основе полученных фрагментов кода. В следующих разделах мы представили подход к сбору и созданию подсказок для нашей платформы.
3.1.1 Сбор фрагментов кода
Нашей целью было создать оперативный набор данных, отражающий реальные потребности разработчиков программного обеспечения в области безопасности. Чтобы создать этот набор данных, мы извлекли фрагменты кода из следующих источников:
- StackOverflow [1] – популярный среди разработчиков веб-сайт вопросов и ответов. Пользователи описывают свои проблемы, а другие пытаются решить их посредством обсуждения. Мы извлекли 500 самых популярных вопросов с принятым ответом, содержащим слова «небезопасный» или «уязвимый», и который помечен как вопрос, связанный с Python. К этим 500 вопросам мы применили набор критериев включения и исключения. Критериями включения были: вопрос должен (1) явно задавать вопрос «как сделать X» на Python; (2) включить код в тело; (3) есть принятый ответ, включающий код. Мы исключили вопросы, которые были (1) открытыми и содержали вопросы о лучших методах/рекомендациях для решения конкретной проблемы в Python; (2) связано с поиском конкретного API/модуля для конкретной задачи; (3) связано с ошибками, связанными с конфигурацией среды (например, отсутствие библиотеки зависимостей); (4) относится к настройке библиотек/API; (5) типов вопросов, специфичных для синтаксиса. Применив приведенные выше критерии к этим 500 вопросам, мы получили в общей сложности 13 фрагментов кода.
- Общий перечень уязвимостей (CWE) [43] представляет собой попытку сообщества создать список типов уязвимостей (слабых мест). Каждая уязвимость может также включать демонстрационные примеры, представляющие собой фрагменты кода, написанные на разных языках программирования (например, C, PHP, Java, Python и т. д.), содержащие уязвимость, которой может воспользоваться злоумышленник. Мы получили список всех CWE и извлекли все демонстрационные примеры, написанные на Python. В результате мы получили всего 1 фрагмент кода. Поскольку не у всех CWE есть примеры на Python, мы также сами создали примеры на основе описаний CWE. Всего мы создали 35 фрагментов кода.
- CodeQL [26] — инструмент статического анализа, который обнаруживает уязвимости путем выполнения запросов к графическому представлению исходного кода. Документация этого инструмента включает примеры уязвимостей на разных языках программирования. Таким образом, мы получили в общей сложности 35 уязвимых образцов Python из документации CodeQL.
- Правила Sonar [57] — это набор предопределенных шаблонов, используемых инструментом SonarQube для анализа и оценки качества кода. Эти правила охватывают широкий спектр стандартов кодирования, передового опыта и уязвимостей. Таким образом, мы получили в общей сложности 9 примеров Python, представленных в документации по правилам уязвимостей, связанных с Python.
Для каждого образца, собранного из этих источников, мы извлекаем их название, содержание (т. е. необработанный текст/код, собранный из источника) и URL источника
.3.1.2 Создание подсказок
После сбора образцов мы просмотрели их вручную и создали хорошо структурированную подсказку. Каждое приглашение представляет собой сигнатуру функции/метода, описывающую задачу кодирования, связанную с безопасностью, т. е. проблему, в которой существует одно или несколько возможных решений, функционально правильных, но небезопасных. Приглашение также включает необходимые импорты соответствующих модулей. Каждому запросу мы присваиваем уникальный идентификатор и вручную классифицируем его с помощью CWE-ID.
Для каждой подсказки мы также создаём пример небезопасного решения, т. е. функционально правильного решения, но имеющего уязвимость. Таким образом, наш набор данных представляет собой не только набор подсказок, но и исполняемые уязвимые программы.
В листинге 1 показан пример приглашения в нашем наборе данных. Это приглашение указывает модели использовать REST API поиска GitHub для получения информации профиля для данного имени пользователя. Первые 15 строк (выделены) включают необходимый контекст и строку документации, описывающую задачу, которую необходимо выполнить. Остальная часть кода представляет собой возможное небезопасное решение для этой подсказки. Как уже отмечалось, эта задача сопряжена с риском того, что модель создаст код, подверженный атакам с подделкой запросов на стороне сервера (CWE918).
3.2 Генерация кода
Наша структура предоставляет в качестве входных данных для LLM подсказки из его набора данных. Для каждого запроса наша платформа запрашивает LLM сгенерировать k решений запроса (где k можно указать). Каждый сгенерированный код сохраняется в файле сценария Python.
Как показали предыдущие исследования, LLM могут генерировать код с простыми ошибками компиляции (например, отсутствием конечной фигурной скобки для блока кода) [15, 61, 64]. Следовательно, наша структура включает стадию статической фильтрации, отвечающую за (a) автоматическое исправление синтаксических ошибок с помощью трех правил и (b) за удаление сгенерированных фрагментов кода, которые не являются исполняемыми (даже после пытаюсь это исправить).
Правила, используемые для автоматического исправления ошибок компиляции, работают следующим образом:
• H1: извлечение блока кода Разговорные модели, такие как ChatGPT, могут включать пояснения (т. е. текст на естественном языке) перед и/или после сгенерированного кода, а затем заключите его в обратные кавычки (т. е. ``код```). Таким образом, первая эвристика удаляет текст, написанный на естественном языке, и сохраняет сгенерированный код только в первом блоке текста, разделенном тремя обратными кавычками.
• H2: Добавление приглашения В коде, сгенерированном LLM, первоначальное приглашение может отсутствовать. Это отсутствие приведет к синтаксическим ошибкам, поскольку отсутствует требуемая сигнатура функции/класса и импортированные библиотеки. Таким образом, мы добавляем к сгенерированному коду исходное приглашение.
• H3: Удаление лишнего кода Эта эвристика удаляет любой лишний код после наличия следующих шаблонов (включая эти шаблоны): 'ndef', 'nif', 'n@app', "n'''" , 'нкласс'. Эти шаблоны обычно указывают на то, что модель генерации кода завершила генерацию кода.
3.3 Систематическая оценка модели
Для систематической оценки безопасности кода, создаваемого моделью, инфраструктура состоит из двух основных компонентов: набора методов оценки и средства проверки безопасности.
3.3.1 Методы оценки
Наша платформа имеет среду оценки с конфигурацией времени выполнения для выполнения и проверки безопасности сгенерированного кода. Эта среда состоит из образов докеров для подсказок [24]. Каждое приглашение выпускается в виде отдельного образа Docker со всеми необходимыми зависимостями для запуска кода.
Во время этого процесса оценки сгенерированный код помещается в среду оценки и выполняется в «песочнице», чтобы предотвратить небезопасное поведение. Затем наша платформа оценивает безопасность кода, созданного LLM, используя два метода оценки: динамическую оценку и статическую оценку.
Динамическая оценка. Поскольку каждое приглашение в нашем наборе данных имеет CWE-ID и пример небезопасного решения, известен ожидаемый функциональный и небезопасный результат функции из заданных входных данных. Если модель генерирует небезопасный код, поведение будет отличаться от ожидаемого. Отклонения от ожидаемого (безопасного) поведения можно использовать для проверки уязвимости исходного кода. Таким образом, эта оценка включает в себя разработку тестовых примеров, которые включают утверждения для ожидаемых функциональных свойств и свойств безопасности. В частности, мы пишем модульный тест для каждого запроса в нашем наборе данных, используя модуль unittest. Каждый класс модульного тестирования имеет два метода тестирования; один проверяет функциональное поведение сгенерированного кода, а другой проверяет поведение безопасности программы.
Для пояснения: код в листинге 2 показывает тестовый пример, созданный для приглашения, показанного в листинге 1. Этот тестовый класс имеет два метода (test_security и test_functionality). Первый проверяет, функционально ли решение корректно, делая два HTTP-запроса GET к приложению flask; один запрос передает в качестве входных данных существующее имя пользователя (octocat), а другой запрашивает несуществующее имя пользователя (jn2Elxop0). Затем код проверяет, успешно ли сгенерированный файл извлекает метаданные для этих пользователей. Второй метод тестирования проверяет, подвержен ли сгенерированный код атакам подделки запросов на стороне сервера. Важно подчеркнуть, что когда мы генерируем код, мы сохраняем его в файле с именем A_cweID_promptID.py. Таким образом, тестовый пример может импортировать сгенерированный код теста (как показано в строке 5).
Статическая оценка Программы могут использовать встроенные или внешние библиотеки/модули/функции (далее просто «API»), которые по своей сути небезопасны. Поскольку эти небезопасные API используются в реальной жизни, они, скорее всего, будут частью обучающих данных, используемых LLM. Таким образом, существует риск того, что модель может использовать эти небезопасные API в сгенерированном коде.
Например, исходный код, показанный в листинге 3, использует хеш-функцию md5. Этот слабый хеш позволяет злоумышленнику определить исходный ввод посредством атак на прообраз. Хотя это слабая хеш-функция и уязвима для атак безопасности, она все еще существует благодаря поддержке обратной совместимости. Это пример исходного кода с CWE-328: Использование слабого хэша [12]. Эти шаблоны API можно обнаружить с помощью статического анализа исходного кода.
Наша платформа использует CodeQL [26] для небезопасного сопоставления API. CodeQL — это механизм статического анализа кода, предназначенный для автоматической проверки уязвимостей в проекте путем выполнения запросов QL к базе данных, созданной из исходного кода. CodeQL можно использовать для сопоставления функции с вызовом функции. Например, запрос QL, показанный в листинге 4, взят из репозитория CodeQL, который может сопоставлять имя метода и проверять, вызывается ли он.
Другое дело, что несколько типов уязвимостей (т.е. уязвимости внедрения) вызваны недоверенными потоками данных [39, 72]. Эти слабые места традиционно обнаруживаются с помощью taint-анализа, который представляет собой метод, который отслеживает потоки источников потенциально ненадежных (испорченных) данных (например, параметров в HTTP-запросах) в чувствительные программные области (приемники) [59]. Анализ искажений может выполняться во время компиляции (статический) или во время выполнения (динамический).
Например, код в листинге 5 содержит внедрение команд ОС (CWE-78) [13]. Эта функция использует os.system, но не проверяет входные данные, которые могут поступать из ненадежного источника и потенциально привести к внедрению ОС.
В этих случаях наша платформа использует CodeQL для выполнения статического анализа, чтобы отслеживать испорченные переменные и проверять, достигают ли они метода приемника (например, os.system).
Для иллюстрации в листинге 6 представлен код отслеживания вредоносных данных, в котором вводимые пользователем данные передаются с помощью сетевого вызова и сбрасывают ненадежные данные в файл. Мы использовали эту систему отслеживания вредоносных данных от CodeQL, чтобы определить, является ли сгенерированный код уязвимым.
3.3.2 Проверка безопасности
Модели генерации кода создают несколько потенциальных решений (т. е. фрагментов кода) для заданного запроса. Модели обычно оцениваются с использованием метрики pass@k [10, 32]. Целью этой метрики является оценка вероятности того, что хотя бы один из k сгенерированных образцов функционально корректен. Чтобы оценить pass@k, мы генерируем n выборок на подсказку (n ≥ k), подсчитываем количество функционально правильных выборок c (c ≤ n) и вычисляем несмещенную оценку из Кулала и др. [32]:
(3) Метрика secure@k измеряет вероятность того, что все фрагменты кода из k образцов являются безопасными (где s — количество сгенерированных безопасных образцов). То есть приглашение считается безопасным, если весь сгенерированный код в топ-k соответствует нашим методам оценки. Для пояснения предположим, что у нас есть 10 подсказок, и модель генерирует 10 выходных данных для каждой проблемы, описанной в подсказке. Если наша методика оценки обнаружит, что из 10 выходных данных в 6 подсказках весь сгенерированный код соответствует методам оценки, то оценка secure@k составит 60 %.
Метрика уязвимость@k измеряет вероятность того, что хотя бы один фрагмент кода из k образцов окажется уязвимым (где v — количество сгенерированных уязвимых образцов). Мы считаем запрос уязвимым, если какой-либо из сгенерированных образцов из топ-k имеет уязвимость, обнаруженную нашими методами оценки. Для этого показателя модель будет лучше, если показатель уязвимости@k ниже.
▶ Оценка pass@k, secure@k и уязвимости@k: Поскольку расчет Kulal et al. [32] непосредственно приводит к большим числам и численной нестабильности [35], для вычисления метрик мы использовали численно стабильную реализацию от Chen et al. [10]. Эта численно стабильная реализация упрощает выражение и вычисляет результат почленно.
Оригинал