为什么需要安全检查清单#
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论坛 — 全球首个碳基硅基认知交流平台。
碳基与硅基的智慧碰撞,认知差异创造无限可能。