← 返回目录
ap6.5实操⏱ 约 11 分钟

日志脱敏:你的日志里装着别人的隐私

实测正则漏出 57%,还把身份证误认成手机号——而最强的脱敏是不记录

🔎 最后验证 2026-08📚 来源:本节脱敏实测为 ECS 实测(2026-08,deepseek-chat,12 条虚构日志样本共 14 处敏感项,脚本与原始输出见本节代码)🧰 Python、DeepSeek API
为什么学这个

ap1.6 你把每次调用都记进了流水,ap5.6 你把线上失败样本捞进了评测集。这两件事都很对,但它们同时也在你的服务器上堆起了一座隐私仓库。

用户会在对话框里输入什么?手机号、身份证、地址、银行卡、"我叫张伟"、老板的名片……他们不知道这些会被记进你的日志、进你的评测集、发到你的监控平台。

实测一套典型的正则脱敏器:14 处敏感信息,漏出 8 处(57%);而且它还犯了一个更糟的错——把身份证号当成手机号脱了一半,留下了前 6 位地区码和后 1 位。

这一节讲怎么把这座仓库拆掉。

💡 打个比方

日志脱敏像寄快递前撕掉面单:大部分人记得撕手机号,但忘了盒子侧面还贴着一张分拣条,上面印着你的名字和小区

而最彻底的做法根本不是撕——是一开始就别把这些信息印上去

实测:正则挡得住"格式固定"的,挡不住"要读懂才知道"的

  原文:用户查询:我叫张伟,住在杭州市西湖区文三路 100 号 3 单元 502
    正则:用户查询:我叫张伟,住在杭州市西湖区文三路 100 号 3 单元 502   漏出 ['张伟', '杭州市…502']
    模型:我叫[姓名],住在[地址]。                                    ✅

  原文:用户查询:麻烦联系我先生,他叫李建国,电话一三九零零零零一二三四
    正则:(原样)                                                漏出 ['李建国', '一三九零零零零一二三四']
    模型:用户查询:麻烦联系我先生,他叫[姓名],电话[手机号]                 ✅

  原文:报错堆栈:KeyError at parse_order(body={'phone':'13900002345','name':'王芳'})
    正则:报错堆栈:KeyError at parse_order(body={'phone':'[手机号]','name':'王芳'})   漏出 ['王芳']
    模型:…'phone':'[手机号]','name':'[姓名]'…                        ✅

  敏感项共 14 处
  正则脱敏:漏出 8 处(57%)
  模型脱敏:漏出 0 处(0%)

四类正则的死穴:

  1. 姓名和地址——没有固定格式,只能靠语义;
  2. 中文数字写的手机号("一三九零零零零一二三四");
  3. 账号/用户名(test_user_88、微信号)——和普通字符串没区别;
  4. 报错堆栈和请求体——这是最容易被忘的一处,因为你不是"故意"记它的,是异常捕获顺手 dump 出来的。

一个更糟的错误:正则把身份证脱成了手机号

  原文:用户查询:我的身份证 110101199001011234 实名认证失败
  正则:用户查询:我的身份证 110101[手机号]4 实名认证失败

手机号规则 1[3-9]\d{9} 在身份证号中间匹配上了一段,于是它替换了中间 11 位,留下前 6 位(地区码)和最后 1 位。这比完全没脱还危险——你以为脱过了

教训:多条正则同时作用时,顺序和边界很关键。长模式(身份证、银行卡)必须先匹配,短模式(手机号)加词边界。写完必须用样本测一遍,而不是"看起来对就上线"。

模型脱敏很准,但有它的代价

模型 0 漏出,但看它的实际输出:

  原文:用户查询:我的身份证 110101199001011234 实名认证失败
  模型:我的身份证 [身份证号] 实名认证失败              ← "用户查询:"前缀被吃掉了

  原文:用户查询:银行卡 6222021234567890123 扣款两次了
  模型:银行卡 622202**********9012 扣款两次了       ← 保留了前 6 位(发卡行 BIN)和后 4 位

三个代价:

  • 占位符格式不一致:[姓名]***622202**********9012 混着来——下游按格式解析就会崩;
  • 会改动不该改的:吃掉前缀、加句号、重排语序——日志失真;
  • 每条都要钱、都要几百毫秒:全量日志走模型脱敏,成本和延迟都不现实。

实用组合:正则先跑(免费、快、覆盖结构化 PII),模型只处理"疑似含自由文本 PII"的那部分(比如用户自由输入字段),而且输出必须过一遍校验(ap3.2 的校验器:检查占位符格式、检查长度变化是否离谱)。

最强的脱敏是"不记录"

   {"len": 27, "has_digit": true, "has_cn": true, "pii_kinds": ["手机号"], "sha8": "c4a1bd26"}
   {"len": 36, "has_digit": true, "has_cn": true, "pii_kinds": ["手机号","身份证","银行卡"], "sha8": "af81d8da"}

不存原文,只存结构指纹:长度、字符构成、命中的 PII 类型、内容哈希前 8 位。用它能做的事比你想的多:

  • 同一个 sha8 反复出现 → 用户在重问同一个问题(正好是 ap5.6 的重问信号);
  • pii_kinds 非空 → 这条走高敏感链路,不进评测集、不进监控上报;
  • len / has_cn → 复现输入的"形状"(超长文本?纯数字?),排查大部分格式类 bug 够用了。

做不到的是看到用户到底问了什么——这正是重点。需要看原文时,走审批 + 短期留存 + 全程审计,而不是所有工程师默认可见。

四个最容易漏的地方

位置为什么容易漏
报错堆栈 / 请求体 dump不是你"主动记"的,是 except 里顺手打的(实测漏出王芳)
发给第三方的监控/APM你脱敏了自己的日志,没脱敏发给 Sentry / 阿里云 SLS 的那份
评测集ap5.6 的回流样本直接来自线上——入库前必须脱敏
给模型的提示词本身你把用户资料拼进提示词发给了模型服务商;服务商的日志你管不到

最后一条尤其要认真对待:发给模型的内容,等于交给了第三方。涉及身份证、银行卡、健康信息这类,要么本地处理不发出去,要么先脱敏再发(把"张伟"换成"用户A",拿回结果再换回来)。

🔧 动手做:给你的日志做一次体检(15 分钟)

  1. 跑本节代码,重点看身份证被错脱成手机号那一条,和报错堆栈里漏出的姓名
  2. 翻你自己的日志:随便抓 50 条最近的,肉眼找一遍——你会找到你以为不会在那儿的东西
  3. 修正则的顺序和边界:长模式(身份证、银行卡)先跑,短模式加 \b;用本节的样本集测一遍
  4. except 里的 dump 改掉:别打全量请求体,只打字段名和类型。
  5. 检查第三方上报:发给监控平台的那份脱敏了吗?
  6. 给 ap5.6 的回流管线加一道脱敏闸——入评测集前必过。
  7. 定留存期:原始日志存多久?(建议 7-30 天)过期自动删,写成定时任务,别靠人记得。

做到这里你应该有:修好顺序的正则脱敏器 + 一份脱敏测试样本集 + 改造后的异常日志 + 第三方上报的脱敏 + 一条自动过期删除任务。

为什么:《个人信息保护法》要求处理个人信息遵循最小必要原则,并有明确的存储期限;《生成式人工智能服务管理暂行办法》进一步要求服务提供者依法保护使用者的输入信息和使用记录。但抛开合规不谈,更现实的理由是:你的日志是你整个系统里最容易被拖走的东西——它没有生产库那么高的防护等级,却常常存着同样敏感的内容。不记录的东西,才是真正安全的。

❓ 测验
实测中,正则脱敏把身份证号 110101199001011234 变成了「110101[手机号]4」。这为什么比「完全没脱敏」更危险?
⚠️ 避坑别把「脱敏后的数据」当成「匿名数据」

脱敏 ≠ 匿名。两个常见误区:

① 哈希不是匿名。手机号只有 11 位、身份证的空间也有限——拿哈希值去撞一遍全量手机号,几分钟就还原了。要用就加盐(salt),而且盐要和数据分开存。

② 拼起来就能认出人。单看"杭州市西湖区"不算隐私,但"杭州市西湖区 + 1990 年生 + 某公司 CTO"就足以定位到具体的人。判断标准不是"这个字段敏不敏感",而是"这些字段合起来能不能指向一个人"。

所以在处理敏感场景时,默认动作应该是"不采集",而不是"采集了再想办法脱"。

🤖 让 AI 帮你做一次日志隐私体检
这是我系统里会写进日志的内容类型:【列出:用户输入字段、请求体、错误堆栈、模型输出、第三方上报…】。请帮我:1) 逐项判断可能包含哪些个人信息(按《个人信息保护法》口径,区分一般个人信息与敏感个人信息);2) 给出正则脱敏方案,注明匹配顺序和边界处理(避免长号被短规则误匹配);3) 指出哪些必须用语义识别、正则做不到;4) 给出建议的留存期限和删除策略;5) 生成 15 条脱敏测试样本(含容易误匹配的边界情况)。
✅ 小结

脱敏四句话:正则漏出 57%,姓名/地址/中文数字/账号是它的死穴;顺序和边界写错会「脱一半」,比不脱更危险;模型准但格式不稳、会改动原文、贵——只用在自由文本字段;最强的脱敏是不记录,结构指纹足够排查大部分问题

AP6 最后一节把这些零散的合规点收成一张清单:上线前你必须知道的红线——备案、告知、留存、未成年人保护,以及"哪些事你现在做不了"。

下一节 → 合规底线:上线前必须知道的几条红线
🔎 来源与核验· 3 条,点开核对
本节每个关键论断都对应一个可追溯的来源 —— 这是本课程"靠谱、不过时"的底线。
「12 条日志样本共 14 处敏感项实测:正则脱敏漏出 8 处(57%),模型脱敏漏出 0 处;正则漏出集中在姓名、详细地址、中文数字手机号、账号/微信号,以及报错堆栈中的字段值」
📚 ECS 实测 redact.py 实验一(2026-08,deepseek-chat,样本为虚构数据)✓ 已核验 2026-08
「正则误脱敏实例:身份证 110101199001011234 被手机号规则 1[3-9]\d{9} 在中间匹配,脱敏后输出为「110101[手机号]4」,保留了前 6 位与末位」
📚 ECS 实测 redact.py(2026-08)✓ 已核验 2026-08
「模型脱敏虽 0 漏出,但占位符格式不一致([姓名]/***/部分掩码)且会改动原文(吃掉前缀、加句号)」
📚 ECS 实测 redact.py(2026-08)✓ 已核验 2026-08
智图软件的赞赏码
都看到这了,打个赏呗!
接下来 · ap6.6
合规底线:上线前必须知道的几条
继续读下一节 →