深色模式
数据泄露与隐私保护
摘要:大模型把"泄露"从传统的数据存储扩展到了提示、上下文、日志、检索块、输出多个新面。OWASP LLM Top 10 中 LLM02(Sensitive Information Disclosure)、LLM07(System Prompt Leakage)、LLM08(Vector and Embedding Weaknesses)都指向这一类。本文给出生产可用的脱敏与隔离策略,适用所有接入 LLM 的应用。模型/版本:GPT-4o、Claude 4.x、Gemini 2.x 及自托管模型均适用。
适用版本与前提
- 数据保护法规:GDPR、中国《个人信息保护法》(PIPL)、EU AI Act 透明度义务。
- 技术前提:可观测日志管道、PII 检测能力(正则 + 分类器)、RAG 权限模型。
假设系统提示会被提取
设计原则:假定系统提示一定会被用户提取。因此系统提示里绝不能放 API Key、数据库密码、内部主机名、真实 PII。工具持有凭据在服务端,prompt 只描述"能做什么"。即便整段系统提示泄露,最坏也只是尴尬,而非安全事故。
核心概念:四个泄露面
| 面 | OWASP | 典型后果 |
|---|---|---|
| 提示/系统提示泄露 | LLM07 | 策略暴露、密钥外泄 |
| 输出回显私有数据 | LLM02 | PII/商业机密泄露 |
| RAG 越权检索 | LLM08 | 跨租户数据串 |
| 日志/链路追踪含 PII | LLM02 | 合规违规、审计失败 |
架构:脱敏与隔离流水线
生产实践:把凭据与 PII 挡在 prompt 之外
1) 密钥永远在服务端
API Key 只存在于服务端环境变量;前端永远不持有。工具凭据由后端注入,prompt 里只出现"工具名 + 用途描述"。
bash
# .env (切勿提交; 已在 .gitignore)
ANTHROPIC_API_KEY=sk-ant-api03-...
OPENAI_API_KEY=sk-...1
2
3
2
3
bash
# .gitignore
.env
.env.local
.env.production1
2
3
4
2
3
4
2) 日志脱敏过滤器(必装)
任何进入 LLM 的请求/响应、工具结果在落日志前先过脱敏。下面是一个最小 PII 正则脱敏示例:
python
import re
PII_PATTERNS = {
"email": re.compile(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"),
"phone_cn": re.compile(r"(?<!\d)(1[3-9]\d{9})(?!\d)"),
"id_card_cn": re.compile(r"(?<!\d)(\d{17}[\dXx])(?!\d)"),
"api_key": re.compile(r"(sk-[a-zA-Z0-9-]{20,}|sk-ant-api03-[a-zA-Z0-9-]{20,})"),
}
def redact(text: str) -> str:
for name, pat in PII_PATTERNS.items():
text = pat.sub(f"<{name}>", text)
return text
# 落日志前调用
import logging
logger = logging.getLogger("llm")
logger.info("request=%s", redact(raw_payload))1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
3) RAG 按权限隔离检索(防 LLM08)
向量检索必须带租户/权限过滤,不能在"全量知识库"上检索后直接拼进 prompt。否则一个用户的提问可能召回另一用户私有的切块。
python
# 伪代码: 检索时强制带上 caller 的权限范围
def retrieve(query: str, tenant_id: str, user_scopes: list[str]) -> list[str]:
hits = vector_store.search(
query,
filter={"tenant_id": tenant_id, "min_scope": {"$in": user_scopes}},
)
return hits1
2
3
4
5
6
7
2
3
4
5
6
7
操作步骤:输出侧 PII 拦截
yaml
# output_guard.yml
output_pii:
detectors: [regex_pii, llama_guard4] # [版本相关] llama_guard4 见内容安全篇
action_on_hit: redact # 或 block / escalate_to_human
log: true
system_prompt_policy:
forbid_secrets_in_prompt: true # 构建期校验, 拒绝含密钥的模板上线1
2
3
4
5
6
7
2
3
4
5
6
7
验证
bash
# 1) 注入含 PII 的测试用例, 确认日志中被脱敏
curl -s -XPOST "$APP/chat" -d '{"msg":"我的邮箱 a@b.com 电话 13800000000"}' >/dev/null
grep -c "<email>" "$LOG_FILE" # 应 > 0 表示已脱敏
# 2) 跨租户检索测试: 用户 A 不应召回用户 B 的私有切块
python tests/test_rag_isolation.py --tenant A1
2
3
4
5
6
2
3
4
5
6
回滚与清理
脱敏可能误伤业务文本
强正则可能把正常订单号/工单号误判为 PII。上线先用 action: log_only 观察误杀率,再切 redact/block。保留白名单(如特定格式放行)。
故障排查
- Q:模型仍回显了上下文里的私有数据? 检查是否把整段系统提示/工具结果直接回显给用户,或 RAG 检索未做权限过滤。模型本身不会"记得"训练数据泄露,多为上下文拼接问题。
- Q:日志里还是有密钥? 通常是某条
print/未走脱敏过滤器的旁路日志。全局拦截 stdout 中的密钥模式(pre-commit + 运行时 filter)。
安全与合规
- 训练/推理数据边界:不要把用户 PII 当作训练语料,除非已获同意并做匿名化(对应 LLM04 投毒与隐私)。
- EU AI Act:Article 50 透明度义务要求对 AI 生成内容适当标注;数据保护(GDPR/PIPL)要求默认脱敏与最小化收集。
- 数据驻留:跨境场景注意模型 API 的数据是否出境(如选择区域端点
anthropic.com/v1vs 区域云)。[未实测:需按所选供应商的区域端点确认数据驻留承诺]
成本 / 性能
- 脱敏与 PII 检测增加少量延迟(正则 < 1ms,分类器一次小调用)。相比一次 PII 泄露的合规罚款(EU AI Act 上限 3500 万欧元或全球营业额 7%
[版本相关]),成本可忽略。 - 过度脱敏(把正常内容全挡掉)会损害产品可用性,需在"安全 vs 体验"间调阈值。