
정규식 규칙과 Gemini 분류기를 통해 프롬프트 인젝션 입력을 차단하고, 봇 응답에서 비밀 정보나 시스템 프롬프트 유출을 잡아내는 2계층 LLM 방화벽입니다.
라이브 데모: https://prompt-injection-firewall.streamlit.app 2분 데모 영상: https://drive.google.com/file/d/1tzb75nFysisrCYa11Lqj6egDs5VNmc2n/view?usp=drivesdk
LLM 지원 봇을 위한 2계층 방화벽으로, 사용자가 보내는 입력과 봇이 내보내는 출력을 모두 검사합니다.
사용자는 봇의 규칙을 무시하도록 시도하거나("이전 지시를 무시하라"), 봇의 페르소나를 바꾸거나, 시스템 프롬프트나 비밀 정보를 노출시키려 할 수 있습니다. 이 프로젝트는 그러한 입력을 차단하고, 봇의 응답에서 유출을 탐지하며, 실패하는 경우를 포함하여 얼마나 잘 작동하는지 측정합니다.
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을 반환할 수 있으며, 코드는 대기 후 재시도합니다.
data\cases.jsonl을 다시 빌드하려는 경우가 아니라면 src\build_cases.py를 실행하지 마세요(파일을 덮어씁니다. 동일한 시드는 동일한 케이스를 생성합니다).
deepset/prompt-injections(Apache-2.0)에서 25개 샘플링(시드 7): 공격 12개, 정상 13개. 분할: dev 15개, hidden 10개.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 |
hidden 세트에는 공격이 3개뿐이라 신호가 약합니다. dev에서 분류기 프롬프트를 튜닝했기 때문에 dev와 hidden을 별도로 보고합니다.
수치가 포함된 전체 이력은 CHANGELOG.md에 있습니다. 요약하면: