
Двухуровневый межсетевой экран для LLM, который блокирует входные данные с внедрением промптов с помощью правил regex и классификатора Gemini, а также перехватывает утечки секретов или системных промптов в ответах бота.
Живая демонстрация: https://prompt-injection-firewall.streamlit.app 2-минутное демо-видео: https://drive.google.com/file/d/1tzb75nFysisrCYa11Lqj6egDs5VNmc2n/view?usp=drivesdk
Двухуровневый межсетевой экран для чат-бота поддержки на базе LLM: он проверяет то, что отправляют пользователи, и то, что бот отправляет в ответ.
Пользователи могут попытаться переопределить правила бота («игнорируй предыдущие инструкции»), сменить его персону или заставить его раскрыть свой системный промпт или секреты. Этот проект блокирует такие входные данные, перехватывает утечки в ответах бота и измеряет, насколько хорошо он работает, включая случаи, когда он даёт сбой.
user input
|
v
[1] Rule layer (regex, fast, free) --match--> BLOCK
|no match
v
[2] LLM classifier (Gemini, JSON output, Pydantic validation, retries, fail-closed) --attack--> BLOCK
|benign
v
AcmeBot (Gemini + system prompt)
|
v
[3] Output check (canary token, secret patterns, system-prompt fragments) --leak--> BLOCK
|clean
v
answer to user
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements.txt
copy .env.example .env # then put your Gemini key in .env
python src\run_eval.py dev
python src\eval_output.py dev
python src\compare.py dev
streamlit run app.py # local demo
Используемая модель: gemini-3.1-flash-lite. Бесплатный тариф может возвращать 503 при высокой нагрузке; код ожидает и повторяет попытку.
Не запускайте src\build_cases.py, если только вы не хотите пересобрать data\cases.jsonl (он перезаписывает его; тот же seed даёт те же кейсы).
deepset/prompt-injections (Apache-2.0): 12 атак, 13 безвредных. Разбиение: 15 dev, 10 hidden.data/train.parquet включён в репозиторий (источник: deepset/prompt-injections, Apache-2.0).| Набор | Слой | Результат |
|---|---|---|
| dev | только правила | детекция 2/9, ложное срабатывание 0/6 |
| dev | правила + Gemini (финал) | детекция 8/9, ложное срабатывание 0/6 |
| dev | проверка вывода (финал) | утечка поймана 4/4, ложное срабатывание 0/4 |
| hidden | правила + Gemini | детекция 3/3, ложное срабатывание 0/7 |
| hidden | проверка вывода | утечка поймана 3/3, ложное срабатывание 0/1 |
Файрвол против отсутствия файрвола:
| Без | С | |
|---|---|---|
| dev: атаки, дошедшие до бота | 9/9 | 1/9 |
| dev: безвредные, ошибочно заблокированные | 0/6 | 0/6 |
| hidden: атаки, дошедшие до бота | 3/3 | 0/3 |
| hidden: безвредные, ошибочно заблокированные | 0/7 | 0/7 |
В скрытом наборе всего 3 атаки, поэтому это слабый сигнал. Dev и hidden отчитываются отдельно, потому что я настраивал промпт классификатора на dev.
Полная история с цифрами — в CHANGELOG.md. Кратко: