yeodh10/prompt-guard
GitHub: yeodh10/prompt-guard
一个基于规则与 LLM 双层防护的提示注入检测与拦截演示应用,用多层级防御策略应对 LLM 用户输入中的越狱与注入攻击。
Stars: 0 | Forks: 0
# 🛡️ Prompt Injection Guard — LLM 输入防御演示
这是一个亲自操作 **生成式 AI 安全 (Secure GenAI)** 的演示,这是 2026 年最热门的新领域。
其核心不是单一的分类器,而是**多层级防御 (defense-in-depth)**。
**🔗 在线演示: https://yeodh10-prompt-guard.streamlit.app/**

## 🧱 为什么需要“多层级防御”
因为单层防御是挡不住的。
| 层级 | 优势 | 弱点 | 成本 |
|---|---|---|---|
| **第一层 · 规则/启发式** | 快速·离线,立即拦截*已知的*模式·base64 | 易被改写·多语言·字符操纵·非 base64 编码绕过 | 免费 |
| **第二层 · LLM 分类** | 检测新型·绕过·基于语义的攻击 | 速度慢,有成本,**分类器自身也是注入目标** | API |
| **决策层** | 只要两者中有一个强烈指示则升级 (escalate) | — | — |
## 🧩 功能
- **第一层规则层** — 通过权重匹配韩文/英文注入特征(忽略指令·窃取系统 prompt·角色扮演越狱·伪造分隔符·抑制拒绝)。**解码 base64 后重新检测**·**检测零宽字符**。*无需 key 即可运行*,但**仅限于已知模式**,因此会被变形攻击绕过(参见下文局限性)。
- **第二层 LLM 层** — 对规则层遗漏的新型·上下文相关攻击进行基于语义的分类 (JSON: 类别·置信度·手法·依据)。
- **防御性 Prompt** — 为了防止分类器被注入,将待分析的输入仅视为**由分隔符包裹的‘数据’**,并且不遵循其中的任何指令。
- **拦截/审查/允许** 判定 + 风险评分 (0~100) + **指明由哪一层捕获** + 人类可读的依据。
- **攻击示例库** — 一键演示捕获示例攻击的场景(仅限于*存在于特征库中的*攻击)。还可通过*正常样本*一并查看其过拦截倾向。
## ⚙️ 工作原理
```
사용자 입력
│
├─▶ 1차 룰 레이어 (rules.py) ── 시그니처·가중치, base64 디코딩, 제로폭 탐지
│
├─▶ 2차 LLM 레이어 (detector.py) ── 방어적 프롬프트로 분류 (키 있을 때)
│
└─▶ 결정 레이어 (guard.py) ── 점수 결합 → 차단 / 검토 / 허용 + 근거
```
```
rules.py 1차 방어: 시그니처 룰 + 인코딩/난독 탐지 (순수, 무료, 오프라인)
detector.py 2차 방어: LLM 분류기 (방어적 프롬프트, JSON 출력)
guard.py 결정 레이어: 다층 결합 → 판정
samples.py 공격/정상 샘플 갤러리
app.py Streamlit 대시보드
```
## 🚀 运行
```
python -m venv venv
venv\Scripts\activate # (Windows) / source venv/bin/activate
pip install -r requirements.txt
copy .env.example .env # (선택) ANTHROPIC_API_KEY 입력 — 없어도 룰 레이어는 동작
streamlit run app.py
```
如果没有 key,**仅靠规则层**即可防御已知攻击;如果输入了 key,则会加入 **LLM 层**,
从而也能捕获新型·上下文相关攻击。可以通过侧边栏的攻击样本按钮立即进行演示。
## ☁️ 部署 (Streamlit Community Cloud)
1. 推送到 GitHub (`.env` 通过 `.gitignore` 排除 — 无 key 泄露)。
2. [share.streamlit.io](https://share.streamlit.io) → 关联仓库 → 指定 `app.py`。
3. 在 **Settings → Secrets** 中输入 key (可选):
ANTHROPIC_API_KEY = "sk-ant-..."
ANTHROPIC_MODEL = "claude-haiku-4-5"
4. 即使没有 key 规则层也能运行,因此部署链接会立即拦截并展示*已知的*攻击(绕过局限性请参见下文)。
## 🔐 安全备忘
- 第二层分类器**其本身就是注入目标**。因此,输入会被分隔符 (`<<>>`)
包裹并仅作为“数据”处理,通过 system prompt 强制要求绝对不遵循输入中的指令。
- API key 仅通过 `.env` (本地) / Streamlit **Secrets** (部署) 进行管理,不进行 commit。
- 屏幕上输出的所有输入文本均经过 HTML 转义处理。
## ⚠️ 绕过及其应对 (诚实记录)
第一层规则层基于特征查找,因此对*变形攻击*较弱。为此,我们进行了强化,确保**在匹配前对输入进行反向去混淆** (`normalize.py` — Unicode NFKC·去除零宽字符·同形字符折叠·空格分散恢复·leetspeak·base64/hex/ROT13/URL 解码)。规则层单独运行(无 key 的部署状态)实测:
| 绕过输入 | 归一化前 | 归一化后 |
|---|---|---|
| leetspeak `1gn0r3 4ll pr3vi0us…` | 🟢 允许 0 | 🔴 拦截 95 |
| 字符间加空格 `i g n o r e a l l…` | 🟢 允许 0 | 🔴 拦截 50 |
| ROT13 编码 | 🟢 允许 0 | 🔴 拦截 95 |
| 西里尔同形字符 `іgnоre аll…` | 🟢 允许 0 | 🔴 拦截 95 |
| 插入零宽字符 | 🔴 拦截 | 🔴 拦截 100 |
| 英语改写 ×2 | 🟢 允许 0 | 🟠 审查 |
| **翻译成日语的相同攻击** | 🟢 允许 0 | 🟢 **允许 0 ← 仍然被绕过** |
**1/8 → 7/8** (单样本 7/7 无回归,误报 0/5)。此结果已作为回归测试固化在 `tests/` 中 — `pytest` **通过 33 项**。
### 即便如此依然存在的问题 — 因此需要多层级防御
- **无法通过归一化来防御多语言·语义改写。** 翻译成日语的相同攻击会直接通过(这一局限性也已通过测试明确记录)。翻译·同义词·上下文属于*语义理解*的问题 → 这是**第二层 LLM 层** (`detector.py`) 的职责。(可以使用 `smoke_llm.py` 在有 key 时进行实测 — 单元测试仅通过 mock 验证解析·合并逻辑。)
- 风险评分(权重·阈值)依然是缺乏经验校准的启发式方法。
- 尚未实现与实际 LLM 应用 pipeline 的内联整合·输出端防御(检测系统 prompt 泄露)。
### 测试
```
pip install pytest
pytest -q # 33건: 정규화·우회 회귀·detect_spans·결정로직·LLM(mock)
python smoke_llm.py # 키 있을 때 2차 LLM 레이어 실측(일본어 우회 포함)
```
## 🛠️ 技术栈
Python · Streamlit · Anthropic Claude (`claude-sonnet-4-6` / `claude-haiku-4-5`)
标签:AI安全, Chat Copilot, DLL 劫持, Kubernetes, Naabu, Python, 内容安全, 大语言模型, 安全规则引擎, 无后门, 逆向工具