3,583 papers
arXiv:2610.24907 79 17 окт. 2026 г. FREE

CAT-RAG: безопасный код через короткие подсказки по категориям угроз вместо длинных справок по каждой уязвимости

КЛЮЧЕВАЯ СУТЬ
Почти вдвое больший прирост безопасности кода и минус 40% токенов, причём без смены модели. Всё дело в том, как подавать знания о защите. Метод CAT-RAG позволяет получать от модели более безопасный код, добавляя к запросу только нужные правила. Не нужно заваливать её справками по десяткам уязвимостей. Фишка: группируй знания по теме задачи (файлы, сеть, ввод), а не по номерам уязвимостей. Лёгкая модель-категоризатор читает запрос и выбирает 1–3 категории из списка в ~10 штук. К запросу дописываются 5–6 коротких правил и один мини-пример безопасного кода только по этим категориям.
Адаптировать под запрос
⚡

TL;DR

CAT-RAG — это двухшаговая схема. Сначала лёгкая модель-«категоризатор» читает ваш запрос на код и выбирает из готового списка 1–3 категории безопасности («Валидация ввода и инъекции», «Файлы и пути», «Десериализация»). Затем к запросу добавляются короткие правила и один маленький пример безопасного кода только по этим категориям. Модель, которая пишет код, остаётся прежней.

Главная находка: подсказки на уровне отдельных уязвимостей (CWE) раздувают промпт. Один запрос обычно задевает сразу несколько родственных слабостей, и в контекст попадают десятки справочных абзацев. Внимание модели размывается, а код получается не лучше. Разработчик к тому же думает задачами («прочитать файл, загрузить в память, обработать»), а не номерами уязвимостей. Поэтому справка «по CWE-119» плохо ложится на запрос.

Суть метода: группировать знания по предметной области задачи и подавать ровно столько категорий, сколько нужно запросу. Простой запрос получает одну категорию, сложный — три и больше. У авторов так удалось почти вдвое улучшить прирост безопасности по сравнению с прошлым лучшим методом и сократить расход токенов примерно на 40%.

🔬

Схема метода

ПОДГОТОВКА (один раз): 
  список категорий на язык (~10) → у каждой: 5–6 правил + мини-пример безопасного кода с пометками CWE
  (черновики правил и примеров авторы писали с помощью LLM, список категорий — эксперт)

ШАГ 1: Категоризатор читает запрос → язык + ранжированный список категорий (сколько нужно — 1, 2, 3…)
ШАГ 2: К исходному запросу дописываются правила и примеры выбранных категорий → генерация кода
(ШАГ 3, опционально): LLM сжимает выбранные правила до короткой выжимки → отдельный вызов

Шаги 1 и 2 — два отдельных запроса. Их можно делать вручную в двух сообщениях или поручить агенту.

🚀

Пример применения

Сильная зона метода: задача на генерацию функции или эндпоинта на языке из списка (C, C++, Python, Java), где в одном запросе смешано несколько рисков: файлы, ввод пользователя, сеть. Простые «посчитай сумму» не подходят: там нечего защищать.

Задача: Python-разработчик интернет-магазина на FastAPI делает эндпоинт «Загрузить реестр заказов от поставщика». Пользователь присылает ZIP с CSV, сервис распаковывает его, читает и по ссылке из файла скачивает фото товара. В одном запросе сразу три зоны риска: пути в архиве, разбор данных и исходящие запросы.

Промпт, шаг 1 (категоризатор):

Ты — категоризатор запросов по безопасности кода.

Язык: Python.
Список категорий:
1. Input Validation & Injection
2. OS Cmd Execution
3. File Ops & Path Traversal
4. Deserialization & Data Parsing
5. Authentication & Session Mgmt
6. Cryptography & RNG
7. Error Handling & Info Disclosure
8. HTTP Security & Web Apps
9. SSRF
10. Resource Mgmt & DoS

Запрос разработчика:
«Напиши эндпоинт FastAPI: пользователь загружает ZIP с CSV-реестром заказов,
сервис распаковывает архив, читает CSV и скачивает фото товара по ссылкам из файла».

Верни ранжированный список ID категорий, которые реально задевает этот запрос.
Число категорий выбери сам: простому запросу — одну, сложному — больше. Не добивай список до фиксированного числа.
Формат: «ID — название — одна фраза, почему».

Промпт, шаг 2 (генерация):

Напиши эндпоинт FastAPI: пользователь загружает ZIP с CSV-реестром заказов,
сервис распаковывает архив, читает CSV и скачивает фото товара по ссылкам из файла.

Учти следующие правила безопасности и примеры (категории выбраны под этот запрос):

[Категория 3. File Ops & Path Traversal — Best Practices]
{правила}
[Secure Code Example]
{мини-пример с пометками CWE}

[Категория 9. SSRF — Best Practices]
{правила}
[Secure Code Example]
{мини-пример}

[Категория 10. Resource Mgmt & DoS — Best Practices]
{правила}
[Secure Code Example]
{мини-пример}

Результат: на шаге 1 придёт короткий список из трёх-четырёх категорий с обоснованием. На шаге 2 модель выдаст код эндпоинта. В нём ожидаемо появятся проверки путей внутри архива, ограничение размера, запрет обращений к внутренним адресам и лимиты. Содержание зависит от того, что вы положили в правила и примеры. Результат всё равно проверьте анализатором или ревью: метод повышает долю безопасного кода, но не гарантирует её.

🧠

Почему это работает

Слабость. Длинный контекст с кучей справочных материалов размывает внимание модели, лишнее мешает. Справка по каждой отдельной уязвимости быстро разрастается: один запрос задевает много родственных CWE. К тому же универсальные советы «для всех языков» путают модель, потому что часть из них не подходит к вашему языку.

Сильная сторона. Модель хорошо понимает, о чём задача: файлы, память, сеть, шифрование. Распознать предметную область по запросу ей легко, и для этого хватает даже небольшой модели.

Как метод это использует. Выбор нужных знаний отдан тому, что модель делает хорошо: она определяет область. Знания лежат упакованными по областям: коротко, на нужном языке, с примером. Модель получает только то, что относится к запросу.

Рычаги управления: - Число категорий (dynamic k). Пусть категоризатор сам решает, сколько брать. Для простых запросов это экономит контекст. Для сложных ограничьте потолком (авторы тестировали 1–3 и 1–5). - Список категорий. Сделайте его под свой язык и стек. Авторы строили отдельные списки для C, C++, Python и Java. Часть категорий общая, часть своя (десериализация есть для Python и Java, RAII и шаблоны только для C++). - Размер правил и примеров. Короткие маркированные правила и минимальный код лучше длинных. Если правила разрослись, добавьте шаг сжатия (шаг 3). Он стоит лишнего вызова. - Пометки CWE в примерах кода. Комментарии вида /* CWE-22 */ показывают модели, какая строка от какого риска защищает.

📋

Шаблон промпта

1. Категоризатор:

Ты — категоризатор запросов по безопасности кода.

Язык: {язык}
Список категорий (ID — название):
{список_категорий}

Запрос разработчика:
«{запрос}»

Задача:
1. Определи язык запроса.
2. Верни ранжированный список ID категорий, которые этот запрос реально задевает.
3. Количество категорий выбери сам по сложности запроса: простому — одну, сложному — несколько.
4. Не добавляй категории «на всякий случай».

Формат: ID — название — почему (одна фраза).

2. Запись категории в базе знаний (формат из исследования):

### {ID}. {Название категории} — Best Practices
- {правило 1}
- {правило 2}
- {правило 3}
- {правило 4}
- {правило 5}

### Secure Code Example ({язык})
{минимальный пример безопасной реализации; в комментариях — ссылки на CWE, от чего защищает каждая проверка}

3. Итоговый запрос:

{исходный_запрос}

Учти правила безопасности ниже. Они подобраны под эту задачу.

{записи_выбранных_категорий}

Подставляйте: {язык} и {список_категорий} — ваш список (~10 штук на язык, см. таблицу авторов в разделе «Оригинал»), {запрос} — задачу как её сформулировал бы разработчик, {записи_выбранных_категорий} — то, что выбрал категоризатор.

🚀 Быстрый старт — вставь в чат:

Вот шаблон CAT-RAG (категоризатор + запись категории + итоговый запрос).
Адаптируй под мою задачу: [язык и стек, тип проектов].
Задавай вопросы, чтобы заполнить поля.

[вставить шаблон выше]

LLM спросит язык, стек и типичные задачи (загрузка файлов, платежи, API, работа с БД). Эти ответы нужны, чтобы составить список категорий под ваш язык и написать для каждой короткие правила и мини-пример. Именно в этом основа метода: чем точнее категории совпадают с вашими задачами, тем полезнее подсказки. Авторы тоже делали черновики правил и примеров с помощью LLM.

⚠️

Ограничения

⚠️ Это начальная версия базы знаний. Авторы сами пишут, что категории не покрывают все CWE и сложные случаи. Базу собирал эксперт вручную, её качество напрямую определяет результат.

⚠️ Измеряли «статические проверки не нашли проблем», а не «код безопасен». Основная метрика — доля кода, где анализаторы (Semgrep, Weggli, CodeQL) не сработали. Это не замена ревью и пентесту.

⚠️ Проверяли на небольших открытых моделях для кода. Это модели уровня 7–16 млрд параметров, которые часто генерируют небезопасный код. У современных сильных моделей выигрыш может быть меньше. Категоризатором служили Mistral-7B и GPT-5-mini.

⚠️ Только четыре языка (C, C++, Python, Java) и функции уровня одного запроса. Для больших многофайловых проектов вывод не проверялся.

⚠️ Лишний вызов. Категоризатор добавляет один запрос. Шаг сжатия добавляет ещё один. Для разовых задач в чате проще один раз вручную выбрать категории.

⚠️ Работоспособность кода отдельно. По сходству с эталоном код в целом не ухудшился, но в Java сходство немного упало. На кодовых бенчмарках с тестами авторы проверяли работоспособность отдельно. Цифр этих тестов в доступной части текста нет.

🔍

Как исследовали

Идея была в том, что уязвимости кучкуются по предметной области. Работа с файлами тянет за собой обход путей, символические ссылки и загрузку опасных типов. Поэтому справку по CWE авторы заменили компактными категориями по ~10 штук на язык. В каждой короткие правила и мини-пример с пометками CWE.

Сравнивали с чистой генерацией без подсказок и с прошлым лучшим подходом CodeGuarder. Измеряли долю безопасного кода по статическим анализаторам. Работоспособность проверяли отдельно: на HumanEval и CodeGuard+ с тестами. Взяли три открытые модели для кода и категоризаторы Mistral-7B и GPT-5-mini. Основной бенчмарк — CyberSecEval, 1 066 задач на C, C++, Java и Python.

Проверили четыре сценария: категории отдельно, категории поверх обычного RAG с примерами кода, категории с шагом сжатия и сценарий с «отравленной» базой примеров, куда подложили уязвимый код. Результат: прирост безопасности почти вдвое выше прошлого метода (около 24% против 12% относительно базовой генерации), а расход токенов ниже примерно на 42%. Например, у Qwen-Coder на C доля безопасного кода выросла с 55,5% до 67,0%, на Java с 44,1% до 53,7%.

Удивительно, что короче оказалось лучше. Больше знаний не значит лучше код. Важнее подать нужное, коротко и на нужном языке. Для практики отсюда следует, что инструкции по безопасности стоит держать тематическими блоками и подключать выборочно, а не сваливать весь свод в одну простыню.

📄

Оригинал из исследования

Запись категории «File & Path Operations» для языка C (в статье код усечён, дословно):

File & Path Operations - Best Practices
• Canonicalize and validate all file paths
• Restrict access to allowed base directories
• Check file type and size before processing
• Use O_NOFOLLOW to prevent symlink attacks
• Never trust user-provided filenames

#include 
/* Path traversal prevention (CWE-22/434) */
int safe_open(const char *base,
const char *user_path) {
char full[PATH_MAX],
cb[PATH_MAX], cf[PATH_MAX];
if (!realpath(base, cb)) return -1;
snprintf(full, sizeof(full),
"%s/%s", cb, user_path);
if (!realpath(full, cf)) return -1;
/* CWE-22 */
if (strncmp(cb, cf, strlen(cb)) != 0)
return -1;
/* CWE-59 */
int fd = open(cf, O_RDONLY|O_NOFOLLOW);
if (fd < 0) return -1;
struct stat st;
/* CWE-434 */
if (fstat(fd,&st)||!S_ISREG(st.st_mode)
||st.st_size>10485760){
close(fd); return -1;
}
return fd;
}

Категории по языкам (Python и Java почти совпадают):

Python: Input Validation & Injection; OS Cmd Execution; File Ops & Path Traversal;
Deserialization & Data Parsing; Authentication & Session Mgmt; Cryptography & RNG;
Error Handling & Info Disclosure; HTTP Security & Web Apps; SSRF; Resource Mgmt & DoS

Контекст: это формат записи базы знаний и список категорий, которые авторы использовали в экспериментах. Сам промпт категоризатора в доступной части не приведён: известно лишь, что ему дают полный список названий категорий и просят вернуть язык и ранжированный список ID.

💡

Адаптации и экстраполяции

💡 Адаптация для агента (Claude Code, Cursor): категории как файл инструкций. Это моё применение, в статье его нет. Положите в проект файл SECURITY.md с блоками-категориями и добавьте в CLAUDE.md или AGENTS.md:

Перед написанием кода, который работает с файлами, сетью, вводом пользователя,
БД, шифрованием или процессами:
1. Открой SECURITY.md и выбери 1–3 категории, которые реально задевает задача.
   Если задача простая — выбери одну или ни одной. Не подключай всё подряд.
2. Назови выбранные категории одной строкой в начале ответа.
3. Следуй правилам этих категорий и сверься с их примером кода.

Агент сам играет роль категоризатора, а лишнее не лезет в контекст. Работоспособность такой связки в статье не проверялась.

🔧 Техника: добавить второй проход → поймать пропущенную категорию. После генерации попросите: «Проверь код по тем же категориям и ещё раз по списку: не задел ли он категорию, которую ты не выбрал?» Это отдельная проверка, авторы её не тестировали.

🔗

Ресурсы

  • Работа: Improving Secure Code Generation with Category-Aware Agentic Retrieval (CAT-RAG)
  • Авторы: Mahdieh Abazar, Lorenzo De Carli, Benjamin Tan — University of Calgary
  • Бенчмарки: CyberSecEval (Meta, Purple Llama), CodeGuard+, HumanEval
  • Сравнение с: CodeGuarder (прежний лучший метод), также SecGuide, SOSecure, RESCUE, SecCoder
  • Источники категорий: MITRE CWE Top 25, эмпирическое исследование уязвимостей в коде, сгенерированном LLM
  • Код и база знаний: авторы публикуют их в артефактах работы (ссылки в предоставленном тексте нет)

📋 Дайджест исследования

Ключевая суть

Почти вдвое больший прирост безопасности кода и минус 40% токенов, причём без смены модели. Всё дело в том, как подавать знания о защите. Метод CAT-RAG позволяет получать от модели более безопасный код, добавляя к запросу только нужные правила. Не нужно заваливать её справками по десяткам уязвимостей. Фишка: группируй знания по теме задачи (файлы, сеть, ввод), а не по номерам уязвимостей. Лёгкая модель-категоризатор читает запрос и выбирает 1–3 категории из списка в ~10 штук. К запросу дописываются 5–6 коротких правил и один мини-пример безопасного кода только по этим категориям.

Принцип работы

Два отдельных запроса. Сначала категоризатор получает вопрос: «какие области безопасности задевает эта задача?». Он возвращает ранжированный список. Простому запросу достаётся одна категория, сложному три и больше. Потом выбранные правила и примеры дописываются к исходной задаче, и код пишет прежняя модель. Представь справочную службу. Раньше ты вываливал на модель весь свод законов по каждой статье. Теперь дежурный сначала спрашивает: «Вы по какому вопросу?». И выдаёт одну тонкую папку. Правила подаются по теме задачи, а не по номеру уязвимости, и ровно в том количестве, которое нужно запросу.

Почему работает

Один запрос задевает сразу много родственных слабостей из каталога CWE (это номерной список типовых уязвимостей). Справка по каждой из них раздувается до десятков абзацев. Внимание модели размывается, а код не становится лучше. Универсальные советы «для всех языков» ещё и путают: часть из них к вашему языку не подходит. Разработчик думает задачами: «прочитать файл, загрузить в память, обработать». Справка «по CWE-119» плохо ложится на такой запрос. Определить область задачи модели легко, и для этого хватает даже небольшой модели. Авторы брали Mistral-7B и GPT-5-mini. Выбор знаний отдан тому, что модель делает хорошо. Остальное обеспечивает короткая база правил на нужном языке. Цифры: прирост безопасности почти вдвое выше, чем у прошлого лучшего метода. Расход токенов примерно на 40% ниже. Но измеряли долю кода, где анализаторы (Semgrep, Weggli, CodeQL) ничего не нашли. Это не то же самое, что «код безопасен». Тестировали на небольших моделях для кода (7–16 млрд параметров), у сильных моделей выигрыш может быть скромнее.

Когда применять

Генерация кода → функция или эндпоинт на C, C++, Python или Java, особенно когда в одном запросе смешаны файлы, ввод пользователя и сеть. Например, загрузка архива, разбор данных и скачивание по ссылкам из файла. Не подходит для простых задач вроде «посчитай сумму»: там нечего защищать. Для больших проектов из многих файлов метод не проверяли. Для разовой задачи в чате проще выбрать категории вручную: лишний вызов не всегда окупается.

Мини-рецепт

1. Составь список категорий: около 10 под свой язык и стек. Например, «Файлы и пути», «Десериализация», «Криптография», «Запросы наружу (SSRF)».
2. Наполни каждую: 5–6 коротких правил и один минимальный пример безопасного кода. В комментариях помечай, какая строка от какого CWE защищает. Черновик может написать LLM, но проверь его сам.
3. Шаг 1, категоризатор: дай модели язык, список и запрос. Попроси ранжированный список ID с причиной в одну фразу.
4. Запрети добивать список: простому запросу одна категория, сложному несколько. Никаких «на всякий случай».
5. Шаг 2, генерация: допиши к исходному запросу правила и примеры выбранных категорий. Поставь потолок в 3 категории (авторы тестировали 1–3 и 1–5).
6. Если правила разрослись: добавь сжатие в короткую выжимку. Это ещё один вызов.
7. Проверь результат: прогони код через анализатор или ревью. Метод повышает долю безопасного кода, но не гарантирует её.

Примеры

[ПЛОХО]: `Напиши эндпоинт FastAPI: загрузка ZIP с CSV, распаковка, чтение, скачивание фото по ссылкам. Учти CWE-22, CWE-23, CWE-36, CWE-59, CWE-73, CWE-502, CWE-918, CWE-400...` и ещё страницы справок по каждому номеру. [ХОРОШО], шаг 1: `Ты — категоризатор запросов по безопасности кода. Язык: Python. Список категорий: 1. Input Validation & Injection ... 9. SSRF 10. Resource Mgmt & DoS. Запрос: «эндпоинт FastAPI: загрузка ZIP с CSV, распаковка, чтение, скачивание фото по ссылкам из файла». Верни ранжированный список ID, которые запрос реально задевает. Число выбери сам, не добивай список. Формат: ID — название — почему.` [ХОРОШО], шаг 2: `Напиши эндпоинт FastAPI: загрузка ZIP с CSV, распаковка, чтение, скачивание фото по ссылкам. Учти правила безопасности ниже, они подобраны под эту задачу. [Категория 3. File Ops & Path Traversal — правила + мини-пример] [Категория 9. SSRF — правила + мини-пример] [Категория 10. Resource Mgmt & DoS — правила + мини-пример]` Вместо десятков абзацев про отдельные уязвимости модель получает три короткие папки. Ожидай проверки путей внутри архива, лимит размера и запрет обращений к внутренним адресам.
Источник: CAT-RAG: Improving Secure Code Generation with Category-Aware Agentic Retrieval
ArXiv ID: 2610.24907 | Сгенерировано: 2026-10-20 13:40

Проблемы LLM

ПроблемаСутьКак обойти
Много справочных материалов в запросе не улучшают ответДобавляешь в запрос правила и справку «на всякий случай». Одна задача задевает много родственных пунктов. Справка по каждому пункту разрастается до десятков абзацев. Внимание модели размывается. Нужное тонет среди лишнего. Ответ не лучше, чем без справки, а токенов уходит больше. Универсальные советы «для всех случаев» ещё и путают, потому что часть не подходит к вашей ситуации.Не давай справку по каждому мелкому пункту. Сгруппируй знания по областям задачи. Одна область = 5–6 коротких правил + один маленький пример. В запрос добавляй только нужные области. Знания пиши под свой язык, стек или предметную область.

Методы

МетодСуть
Двухшаговый отбор подсказок по категориям — в запросе только нужноеПодготовка (один раз): составь список из ~10 категорий под свою область. У каждой — 5–6 коротких правил и один мини-пример. Шаг 1: отдельным запросом дай модели задачу и список категорий. Попроси вернуть ранжированные номера нужных. Формат: ID — название — почему (одна фраза). Шаг 2: допиши к исходной задаче записи только выбранных категорий. Запусти генерацию. Число категорий пусть выбирает модель. Добавь в запрос: «Простому запросу — одну категорию, сложному — несколько. Не добавляй на всякий случай». Для сложных задач поставь потолок, например 3–5. Почему работает: выбор области — лёгкая работа для модели. Саму задачу решает отдельный вызов, и контекст в нём короткий и точный. Когда да: в задаче смешано несколько тем. Есть своя база правил, стандартов или примеров. Запросов много, и экономия токенов важна. Когда нет: задача простая, защищать или учитывать нечего. Запрос разовый, тогда проще выбрать категории вручную. Нет базы знаний, а качество результата зависит от неё напрямую. Метод не заменяет проверку результата. Он повышает долю хороших ответов, но не гарантирует её. Идея не привязана к безопасности кода. Подходит для юридических проверок, редакторских правил, медицинских протоколов, стилевых гайдов.

Тезисы

ТезисКомментарий
Определить область задачи модели легко, хватит небольшойМодель хорошо понимает, о чём запрос: файлы, сеть, деньги, шифрование, текст. Это распознавание темы, а не сложное рассуждение. Поэтому роль «маршрутизатора» можно отдать дешёвой модели. Тяжёлую модель оставь для самой генерации. Применяй: сначала отдельным коротким вызовом классифицируй запрос по теме. Потом собирай подсказки под тему.
📖 Простыми словами

CAT-RAG: Improving Secure Code Generation with Category-Aware Agentic Retrieval

arXiv: 2610.24907

Нейросети пишут дырявый софт не потому, что они тупые, а потому что длинные инструкции по безопасности превращают их контекст в кашу. Когда ты скармливаешь модели гигантские справочники уязвимостей, её внимание просто размывается. Обычный RAG пытается впихнуть в промпт тонны абстрактных правил под все случаи жизни, и на выходе получается полный провал — модель путается и всё равно оставляет уязвимости. Метод CAT-RAG бьёт точно в цель: вместо свалки из макулатуры он даёт модели только то, что реально горит прямо сейчас.

Это как нанять охранника и перед выходом на улицу зачитать ему трёхтомник уголовного кодекса со статьями о браконьерстве и госизмене. Формально подготовил, но в тёмной подворотне вам обоим прилетит по голове, пока он вспоминает нужный параграф. Вменяемый человек просто скажет: «тут срезают кошельки, держи руку на кармане». Модели нужна ровно такая же точечная ориентировка, а не лекция по юриспруденции.

Работает это через жёсткую двухшаговую схему. Сначала лёгкий агент-категоризатор быстро чекает задачу и вешает на неё всего 1–3 категории рисков — скажем, инъекции или файловые пути. Дальше в промпт подтягиваются не сотни описаний CWE, а короткие правила и один микропример чисто под твой стек. Основная модель остаётся прежней, но пишет защищённый код, потому что её перестали грузить чужими проблемами.

Схему гоняли на C, C++, Python и Java при создании сетевых эндпоинтов, где сходятся пользовательский ввод, файлы и база. На тривиальных задачах вроде сортировки списка это нафиг не нужно — там нечего ломать. Но в боевом бэкенде, где в одном запросе намешана куча скрытых угроз, связка из категоризации и микропримеров разносит стандартный раздутый RAG в сухую.

Мораль простая: хватит пихать в контекст энциклопедии с мыслью «вдруг пригодится». Избыточный контекст убивает безопасность, заставляя модель игнорировать главное. Бери легковесный классификатор, сужай фокус до пары правил и получай чистый код без переплат за терабайты мусорных токенов.

Работа с исследованием

Адаптируйте исследование под ваши задачи или создайте готовый промпт на основе техник из исследования.

0 / 2000
~0.5-2 N-токенов ~10-30с
~0.3-1 N-токенов ~5-15с