CoderunED/llm-prompt-firewall
GitHub: CoderunED/llm-prompt-firewall
一个 FastAPI 中间件,通过正则与语义分析的双重评分 pipeline 在 prompt 到达 LLM 前检测并拦截注入攻击。
Stars: 0 | Forks: 0
# LLM Prompt 防火墙
一个 FastAPI 中间件,可在 prompt 到达 LLM 之前对其进行拦截,使用融合 regex 与语义分析的 pipeline 对其进行注入尝试评分,拦截高风险请求,并将所有操作记录到 SQLite 中。本项目作为面向云安全、AI/ML 安全和 DevSecOps 工程师职位的个人作品集项目开发。
## 架构
## 仪表盘与结果
## 检测 Pipeline
每个 prompt 都会经过两个独立的评分层。两者的得分将按 50/50 的比例融合为最终的 `injection_score`。
| 层级 | 实现 | 信号 |
|---|---|---|
| Regex | `scorer.py` — 25+ 种模式 | 显式攻击语法 |
| 语义 | `semantic_scorer.py` — `all-MiniLM-L6-v2`,37 个攻击锚点,余弦相似度 | 改写和混淆攻击 |
| 融合 | `(regex × 0.50) + (semantic × 0.50)` | 最终决策得分 |
得分 `≥ 0.40` 的 prompt 将被拦截并返回 `403` 错误,永远不会到达 LLM。该阈值可通过 `.env` 进行调整。
### OWASP LLM Top 10 映射
每个被拦截的请求都会根据匹配的模式和得分信号,映射到相应的 [OWASP LLM Top 10](https://owasp.org/www-project-top-10-for-large-language-model-applications/) 类别中:
| 类别 | 触发条件 |
|---|---|
| LLM01 — Prompt 注入 | 指令覆盖模式,较高的融合得分 |
| LLM02 — 敏感信息泄露 | 凭据/密钥提取模式 |
| LLM05 — 不当输出处理 | 代码/命令注入模式 |
| LLM06 — 过度代理 | 角色劫持、越狱模式 |
| LLM07 — System Prompt 泄露 | System Prompt 提取模式 |
| LLM10 — 无限制消耗 | Token 泛洪/资源耗尽模式 |
## API 参考
### `POST /api/v1/analyze`
通过防火墙发送 prompt。
**请求**
```
{
"prompt": "What is the capital of France?",
"system_prompt": "You are a helpful assistant."
}
```
**响应 — 允许通过 (200)**
```
{
"status": "ok",
"injection_score": 0.021,
"regex_score": 0.0,
"semantic_score": 0.042,
"risk_level": "low",
"blocked": false,
"matched_patterns": [],
"owasp_categories": [],
"response": "The capital of France is Paris.",
"llm_meta": {
"model": "claude-opus-4-6",
"input_tokens": 24,
"output_tokens": 9,
"latency_ms": 843
}
}
```
**响应 — 已拦截 (403)**
```
{
"status": "blocked",
"injection_score": 0.847,
"regex_score": 0.9,
"semantic_score": 0.794,
"risk_level": "high",
"blocked": true,
"matched_patterns": ["ignore_previous", "reveal_system"],
"owasp_categories": [
{"code": "LLM01", "name": "Prompt Injection", "description": "..."},
{"code": "LLM07", "name": "System Prompt Leakage", "description": "..."}
],
"error": "Prompt blocked: injection risk detected."
}
```
### `GET /api/v1/stats`
返回来自 SQLite 日志的汇总指标。
```
{
"total_requests": 142,
"blocked_requests": 38,
"block_rate_pct": 26.76,
"avg_injection_score": 0.2814,
"by_risk_level": {"low": 89, "medium": 15, "high": 38}
}
```
### `GET /health`
```
{"status": "ok", "version": "1.0.0"}
```
## 快速开始
### 本地运行
```
git clone https://github.com/CoderunED/llm-prompt-firewall
cd llm-prompt-firewall
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# 将你的 ANTHROPIC_API_KEY 添加到 .env
python -m uvicorn app.main:app --reload
# API: http://localhost:8000
# 文档: http://localhost:8000/docs
# Dashboard (单独的终端)
streamlit run dashboard.py
# http://localhost:8501
```
### Docker
```
cp .env.example .env
# 将你的 ANTHROPIC_API_KEY 添加到 .env
docker compose up --build
# API: http://localhost:8000
# Dashboard: http://localhost:8501
```
## 项目结构
```
llm-prompt-firewall/
├── app/
│ ├── main.py # FastAPI app, startup, routing
│ ├── config.py # pydantic-settings config
│ ├── scorer.py # Regex scoring engine (25+ patterns)
│ ├── semantic_scorer.py # Semantic scoring (all-MiniLM-L6-v2)
│ ├── owasp.py # OWASP LLM Top 10 category mapper
│ ├── llm_client.py # Anthropic SDK wrapper
│ ├── logger.py # JSONL request logger
│ ├── database.py # SQLite dual-write logger
│ └── routes/
│ └── analyze.py # POST /analyze, GET /stats
├── tests/
│ ├── conftest.py
│ └── test_scoring.py # 30 tests — clean, direct, paraphrased attacks
├── dashboard.py # Streamlit monitoring dashboard
├── calibrate.py # Calibration script
├── Dockerfile # Multi-stage build
├── docker-compose.yml # API + dashboard services, shared volume
├── .github/workflows/
│ └── ci.yml # GitHub Actions — pytest on push/PR
└── .env.example
```
## 配置
所有选项均可通过 `.env` 配置:
| 变量 | 默认值 | 描述 |
|---|---|---|
| `ANTHROPIC_API_KEY` | — | 必填项 |
| `LLM_MODEL` | `claude-opus-4-6` | Anthropic 模型 |
| `BLOCK_THRESHOLD` | `0.40` | 拦截 prompt 的得分阈值 |
| `REGEX_WEIGHT` | `0.50` | Regex 层在融合得分中的权重 |
| `SEMANTIC_WEIGHT` | `0.50` | 语义层在融合得分中的权重 |
| `APP_ENV` | `development` | `development` 或 `production` |
## 测试套件
```
pytest tests/ -v
```
涵盖三个类别的 30 个测试:
| 类别 | 数量 | 断言 |
|---|---|---|
| `TestCleanPrompts` | 10 | 均未被拦截 |
| `TestDirectAttacks` | 10 | 全部被拦截 |
| `TestParaphrasedAttacks` | 10 | 全部被拦截 |
CI 会在每次向 `main` 分支进行 push 和 PR 时通过 GitHub Actions 运行(`ubuntu-latest`,Python 3.12)。
## 技术栈
| 层级 | 技术 |
|---|---|
| API | FastAPI, Uvicorn, Pydantic |
| 评分 | sentence-transformers (`all-MiniLM-L6-v2`), scikit-learn, regex |
| LLM | Anthropic SDK (`claude-opus-4-6`) |
| 存储 | SQLite (标准库), JSONL 扁平文件 |
| 仪表盘 | Streamlit, Plotly |
| 容器 | Docker, Docker Compose |
| CI | GitHub Actions |
| 语言 | Python 3.12 |
## 安全说明
- 容器以非 root 用户(`firewall`)运行
- API 密钥仅通过环境变量加载 — 永不提交到代码库
- 所有请求均记录用于审计;被拦截的 prompt 包含完整的模式和 OWASP 分类
- 阈值、权重和模型均可在运行时配置,无需修改代码
## 仪表盘与结果
## 检测 Pipeline
每个 prompt 都会经过两个独立的评分层。两者的得分将按 50/50 的比例融合为最终的 `injection_score`。
| 层级 | 实现 | 信号 |
|---|---|---|
| Regex | `scorer.py` — 25+ 种模式 | 显式攻击语法 |
| 语义 | `semantic_scorer.py` — `all-MiniLM-L6-v2`,37 个攻击锚点,余弦相似度 | 改写和混淆攻击 |
| 融合 | `(regex × 0.50) + (semantic × 0.50)` | 最终决策得分 |
得分 `≥ 0.40` 的 prompt 将被拦截并返回 `403` 错误,永远不会到达 LLM。该阈值可通过 `.env` 进行调整。
### OWASP LLM Top 10 映射
每个被拦截的请求都会根据匹配的模式和得分信号,映射到相应的 [OWASP LLM Top 10](https://owasp.org/www-project-top-10-for-large-language-model-applications/) 类别中:
| 类别 | 触发条件 |
|---|---|
| LLM01 — Prompt 注入 | 指令覆盖模式,较高的融合得分 |
| LLM02 — 敏感信息泄露 | 凭据/密钥提取模式 |
| LLM05 — 不当输出处理 | 代码/命令注入模式 |
| LLM06 — 过度代理 | 角色劫持、越狱模式 |
| LLM07 — System Prompt 泄露 | System Prompt 提取模式 |
| LLM10 — 无限制消耗 | Token 泛洪/资源耗尽模式 |
## API 参考
### `POST /api/v1/analyze`
通过防火墙发送 prompt。
**请求**
```
{
"prompt": "What is the capital of France?",
"system_prompt": "You are a helpful assistant."
}
```
**响应 — 允许通过 (200)**
```
{
"status": "ok",
"injection_score": 0.021,
"regex_score": 0.0,
"semantic_score": 0.042,
"risk_level": "low",
"blocked": false,
"matched_patterns": [],
"owasp_categories": [],
"response": "The capital of France is Paris.",
"llm_meta": {
"model": "claude-opus-4-6",
"input_tokens": 24,
"output_tokens": 9,
"latency_ms": 843
}
}
```
**响应 — 已拦截 (403)**
```
{
"status": "blocked",
"injection_score": 0.847,
"regex_score": 0.9,
"semantic_score": 0.794,
"risk_level": "high",
"blocked": true,
"matched_patterns": ["ignore_previous", "reveal_system"],
"owasp_categories": [
{"code": "LLM01", "name": "Prompt Injection", "description": "..."},
{"code": "LLM07", "name": "System Prompt Leakage", "description": "..."}
],
"error": "Prompt blocked: injection risk detected."
}
```
### `GET /api/v1/stats`
返回来自 SQLite 日志的汇总指标。
```
{
"total_requests": 142,
"blocked_requests": 38,
"block_rate_pct": 26.76,
"avg_injection_score": 0.2814,
"by_risk_level": {"low": 89, "medium": 15, "high": 38}
}
```
### `GET /health`
```
{"status": "ok", "version": "1.0.0"}
```
## 快速开始
### 本地运行
```
git clone https://github.com/CoderunED/llm-prompt-firewall
cd llm-prompt-firewall
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# 将你的 ANTHROPIC_API_KEY 添加到 .env
python -m uvicorn app.main:app --reload
# API: http://localhost:8000
# 文档: http://localhost:8000/docs
# Dashboard (单独的终端)
streamlit run dashboard.py
# http://localhost:8501
```
### Docker
```
cp .env.example .env
# 将你的 ANTHROPIC_API_KEY 添加到 .env
docker compose up --build
# API: http://localhost:8000
# Dashboard: http://localhost:8501
```
## 项目结构
```
llm-prompt-firewall/
├── app/
│ ├── main.py # FastAPI app, startup, routing
│ ├── config.py # pydantic-settings config
│ ├── scorer.py # Regex scoring engine (25+ patterns)
│ ├── semantic_scorer.py # Semantic scoring (all-MiniLM-L6-v2)
│ ├── owasp.py # OWASP LLM Top 10 category mapper
│ ├── llm_client.py # Anthropic SDK wrapper
│ ├── logger.py # JSONL request logger
│ ├── database.py # SQLite dual-write logger
│ └── routes/
│ └── analyze.py # POST /analyze, GET /stats
├── tests/
│ ├── conftest.py
│ └── test_scoring.py # 30 tests — clean, direct, paraphrased attacks
├── dashboard.py # Streamlit monitoring dashboard
├── calibrate.py # Calibration script
├── Dockerfile # Multi-stage build
├── docker-compose.yml # API + dashboard services, shared volume
├── .github/workflows/
│ └── ci.yml # GitHub Actions — pytest on push/PR
└── .env.example
```
## 配置
所有选项均可通过 `.env` 配置:
| 变量 | 默认值 | 描述 |
|---|---|---|
| `ANTHROPIC_API_KEY` | — | 必填项 |
| `LLM_MODEL` | `claude-opus-4-6` | Anthropic 模型 |
| `BLOCK_THRESHOLD` | `0.40` | 拦截 prompt 的得分阈值 |
| `REGEX_WEIGHT` | `0.50` | Regex 层在融合得分中的权重 |
| `SEMANTIC_WEIGHT` | `0.50` | 语义层在融合得分中的权重 |
| `APP_ENV` | `development` | `development` 或 `production` |
## 测试套件
```
pytest tests/ -v
```
涵盖三个类别的 30 个测试:
| 类别 | 数量 | 断言 |
|---|---|---|
| `TestCleanPrompts` | 10 | 均未被拦截 |
| `TestDirectAttacks` | 10 | 全部被拦截 |
| `TestParaphrasedAttacks` | 10 | 全部被拦截 |
CI 会在每次向 `main` 分支进行 push 和 PR 时通过 GitHub Actions 运行(`ubuntu-latest`,Python 3.12)。
## 技术栈
| 层级 | 技术 |
|---|---|
| API | FastAPI, Uvicorn, Pydantic |
| 评分 | sentence-transformers (`all-MiniLM-L6-v2`), scikit-learn, regex |
| LLM | Anthropic SDK (`claude-opus-4-6`) |
| 存储 | SQLite (标准库), JSONL 扁平文件 |
| 仪表盘 | Streamlit, Plotly |
| 容器 | Docker, Docker Compose |
| CI | GitHub Actions |
| 语言 | Python 3.12 |
## 安全说明
- 容器以非 root 用户(`firewall`)运行
- API 密钥仅通过环境变量加载 — 永不提交到代码库
- 所有请求均记录用于审计;被拦截的 prompt 包含完整的模式和 OWASP 分类
- 阈值、权重和模型均可在运行时配置,无需修改代码标签:AI安全, Chat Copilot, DevSecOps, FastAPI中间件, Kubernetes, LLM应用防火墙, OWASP LLM Top 10, 上游代理, 提示词注入检测, 版权保护, 请求拦截, 逆向工具