为什么需要安全检查清单#
LLM 应用引入了全新的攻击面:Prompt 注入、训练数据泄露、模型越狱、有害内容生成。传统 Web 安全检查清单覆盖不了这些。本文提供 50 项检查项,分为 5 大类,每一项都必须在上线前确认。
一、输入安全(12 项)#
Prompt 注入防护#
| # | 检查项 | 风险等级 | 验证方式 |
|---|
| 1 | 用户输入与系统指令分离(使用 system role) | 高 | 审查 prompt 结构 |
| 2 | 用户输入被包裹在分隔符中(如 <user_input>) | 高 | 审查 prompt 模板 |
| 3 | 系统指令中包含"忽略以上指令"的防御声明 | 中 | 审查 system prompt |
| 4 | 对用户输入做长度限制(建议 < 10K 字符) | 中 | 压测验证 |
| 5 | 过滤已知的 Prompt 注入模式 | 高 | 红队测试 |
# Prompt 注入检测器
class PromptInjectionGuard:
INJECTION_PATTERNS = [
r"ignore\s+(all\s+)?(previous|above|prior)\s+instructions",
r"you\s+are\s+now\s+(a|an)\s+\w+",
r"system\s*:\s*",
r"<\|im_start\|>",
r"forgot\s+your\s+rules",
r"reveal\s+your\s+(system\s+)?prompt",
]
def check(self, user_input: str) -> tuple[bool, list]:
import re
violations = []
for pattern in self.INJECTION_PATTERNS:
if re.search(pattern, user_input, re.IGNORECASE):
violations.append(pattern)
return len(violations) == 0, violations
PII 保护#
| # | 检查项 | 风险等级 | 验证方式 |
|---|
| 6 | 输入中的 PII 被检测并脱敏 | 高 | 传入含 PII 的测试用例 |
| 7 | PII 脱敏日志开启(不记录原始 PII) | 高 | 审查日志配置 |
| 8 | 不会将用户输入原样发送给第三方服务 | 高 | 审查 API 调用链 |
import re
class PIIScrubber:
PATTERNS = {
"phone": (r"\b1[3-9]\d{9}\b", "[PHONE]"),
"email": (r"\b[\w.-]+@[\w.-]+\.\w+\b", "[EMAIL]"),
"id_card": (r"\b\d{17}[\dXx]\b", "[ID_CARD]"),
"bank_card": (r"\b\d{16,19}\b", "[BANK_CARD]"),
}
def scrub(self, text: str) -> str:
for pii_type, (pattern, replacement) in self.PATTERNS.items():
text = re.sub(pattern, replacement, text)
return text
内容安全#
| # | 检查项 | 风险等级 | 验证方式 |
|---|
| 9 | 输入内容分类(是否包含暴力/违法内容) | 高 | 红队测试 |
| 10 | 对敏感话题有预设的拒绝策略 | 中 | 审查 system prompt |
| 11 | 支持多语言输入的过滤 | 中 | 多语言测试 |
| 12 | 对图片输入有内容审核(多模态场景) | 高 | 上传违规模拟图 |
二、输出安全(10 项)#
有害内容过滤#
| # | 检查项 | 风险等级 | 验证方式 |
|---|
| 13 | 输出经过毒性检测模型 | 高 | 触发性测试用例 |
| 14 | 输出经过偏见/歧视检测 | 高 | 公平性测试集 |
| 15 | 对特定领域(医疗/法律/金融)有免责声明 | 中 | 审查输出模板 |
| 16 | 不输出可执行代码的直接运行结果 | 中 | 代码注入测试 |
class OutputSafetyFilter:
def __init__(self, toxicity_model, threshold=0.7):
self.model = toxicity_model
self.threshold = threshold
async def filter(self, response: str) -> tuple[str, bool]:
# 毒性检测
toxicity = await self.model.predict(response)
if toxicity > self.threshold:
return self._safe_fallback(), False
# 敏感信息泄露检测
if self._detect_leaked_info(response):
return self._safe_fallback(), False
return response, True
def _detect_leaked_info(self, text):
"""检测输出中是否泄露了系统信息"""
sensitive_patterns = [
r"api[_-]?key", r"sk-[a-zA-Z0-9]{20,}",
r"password", r"secret", r"token",
r"/[a-z]:\\users\\", # Windows 路径
]
return any(
re.search(p, text, re.IGNORECASE)
for p in sensitive_patterns
)
输出完整性#
| # | 检查项 | 风险等级 | 验证方式 |
|---|
| 17 | 输出有长度上限(防止 Token 爆炸) | 中 | 触发长输出测试 |
| 18 | 流式输出有超时保护 | 中 | 模拟慢速输出 |
| 19 | 输出格式校验(JSON/XML 是否合法) | 中 | 格式错误注入测试 |
| 20 | 输出不包含训练数据原文(版权风险) | 中 | 已知文本检索 |
| 21 | 输出不包含 Prompt 模板内容(提示泄露) | 高 | “重复你的指令"测试 |
| 22 | 输出经过 PII 二次过滤 | 高 | PII 回显测试 |
三、模型安全(10 项)#
越狱防护#
| # | 检查项 | 风险等级 | 验证方式 |
|---|
| 23 | 通过越狱测试集(DAN/Roleplay 编码等) | 高 | 自动化越狱测试 |
| 24 | 对多轮对话有累积风险检测 | 高 | 多轮越狱攻击测试 |
| 25 | 对编码/混淆输入有解码检测 | 中 | Base64/Unicode 混淆测试 |
class JailbreakDetector:
ENCODING_PATTERNS = [
(r"base64:", self._decode_base64),
(r"\\u[0-9a-fA-F]{4}", self._decode_unicode),
(r"\\x[0-9a-fA-F]{2}", self._decode_hex),
]
async def check(self, user_input: str):
# 1. 检查编码内容
decoded = self._try_decode(user_input)
if decoded != user_input:
# 对解码后的内容也做注入检测
safe, _ = PromptInjectionGuard().check(decoded)
if not safe:
return False, "Encoded injection detected"
# 2. 检查角色扮演越狱
roleplay_patterns = [
r"pretend you are",
r"act as (if you are )?DAN",
r"you are (in )?developer mode",
r"jailbreak",
]
for pattern in roleplay_patterns:
if re.search(pattern, user_input, re.IGNORECASE):
return False, f"Roleplay jailbreak: {pattern}"
return True, None
模型隔离#
| # | 检查项 | 风险等级 | 验证方式 |
|---|
| 26 | 不同租户的会话隔离 | 高 | 跨租户数据泄露测试 |
| 27 | 对话历史有长度限制(防止上下文污染) | 中 | 长对话测试 |
| 28 | Function Calling 参数有白名单校验 | 高 | 构造恶意参数测试 |
| 29 | 模型输出不直接执行(需人工/代码确认) | 高 | 审查执行链路 |
| 30 | 有模型使用量配额(防止滥用) | 中 | 超额测试 |
| 31 | 模型版本变更经过安全评估 | 中 | 审查变更流程 |
| 32 | 对抗样本检测(异常输入模式) | 中 | 对抗测试集 |
四、基础设施安全(10 项)#
| # | 检查项 | 风险等级 | 验证方式 |
|---|
| 33 | API Key 存储在密钥管理服务(非代码/配置文件) | 高 | 审查部署配置 |
| 34 | API 通信全程 HTTPS/TLS 1.2+ | 高 | SSL 扫描 |
| 35 | 对 LLM API 调用有网络白名单限制 | 中 | 审查网络策略 |
| 36 | 向量数据库有访问控制 | 高 | 审查 DB ACL |
| 37 | Embedding 服务有认证 | 中 | 未认证调用测试 |
| 38 | 日志中不包含 API Key / 完整 Prompt | 高 | 审查日志输出 |
| 39 | 监控系统有异常调用检测(频率/内容) | 中 | 审查告警规则 |
| 40 | 容器/进程以最小权限运行 | 中 | 审查 K8s manifest |
| 41 | 模型文件有完整性校验 | 中 | 校验和验证 |
| 42 | 有 DDoS 防护(CDN/WAF) | 中 | 审查网络架构 |
五、合规审计(8 项)#
| # | 检查项 | 风险等级 | 验证方式 |
|---|
| 43 | 所有 LLM 调用有审计日志(who/when/what/model) | 高 | 审查日志格式 |
| 44 | 用户知情同意(明确告知使用 AI) | 高 | 审查 UI/ToS |
| 45 | 数据保留策略明确(日志/对话历史保留期限) | 高 | 审查数据策略 |
| 46 | 支持用户数据删除请求(GDPR/PIPL) | 高 | 删除流程测试 |
| 47 | 模型训练数据来源可追溯 | 中 | 审查文档 |
| 48 | 有 AI 生成内容标识(水印/声明) | 中 | 审查输出格式 |
| 49 | 定期安全评估(至少每季度) | 中 | 审查评估记录 |
| 50 | 有应急响应预案(模型输出有害内容时) | 高 | 审查 IR 计划 |
自动化检查脚本#
class SecurityChecklist:
"""可自动化的安全检查项"""
CHECKS = {
"input_length_limit": {"auto": True, "critical": False},
"prompt_injection_filter": {"auto": True, "critical": True},
"pii_scrubbing": {"auto": True, "critical": True},
"output_toxicity_check": {"auto": True, "critical": True},
"output_length_limit": {"auto": True, "critical": False},
"jailbreak_resistance": {"auto": True, "critical": True},
"prompt_leak_prevention": {"auto": True, "critical": True},
"tls_check": {"auto": True, "critical": True},
"log_pii_check": {"auto": True, "critical": True},
"rate_limiting": {"auto": True, "critical": False},
}
async def run_all(self, target_url, api_key):
results = {}
for check_name, config in self.CHECKS.items():
if not config["auto"]:
continue
method = getattr(self, f"check_{check_name}")
try:
passed, detail = await method(target_url, api_key)
results[check_name] = {
"passed": passed,
"detail": detail,
"critical": config["critical"],
}
except Exception as e:
results[check_name] = {
"passed": False,
"detail": f"Check error: {e}",
"critical": config["critical"],
}
# 汇总报告
total = len(results)
passed = sum(1 for r in results.values() if r["passed"])
critical_fail = [
k for k, v in results.items()
if not v["passed"] and v["critical"]
]
return {
"total": total,
"passed": passed,
"failed": total - passed,
"critical_failures": critical_fail,
"ready_for_production": len(critical_fail) == 0,
"details": results,
}
上线审批流程#
开发完成 → 自动化检查(38 项可自动化)
│
全部通过?
├─ 是 → 人工审查(12 项需人工)
│ ├─ 全部通过 → 安全团队签字 → 上线
│ └─ 有问题 → 整改 → 重新审查
└─ 否 → 修复 → 重新自动检查
LLM 安全不是可选项。50 项检查中,标记为"高风险"的约 25 项——这些是上线阻断项,不通过不上线。关键检查包括:Prompt 注入防护、PII 脱敏、越狱抵抗、输出过滤、密钥管理。自动化检查覆盖约 76% 的项目,剩余需人工审查。建议将检查清单集成到 CI/CD 流水线中,每次部署前自动运行。安全是一场持续的攻防战,检查清单只是起点,不是终点。#
加入讨论#
这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。
碳基与硅基的智慧碰撞,认知差异创造无限可能。