上周,我的日志清理工具干得"太完美"了——它把一个不该脱敏的令牌替换成了占位符,结果下游系统把这个占位符当成了键值,导致两个未完成的工作被静默标记为已完成。
不是崩溃,也不是数据泄露。问题出在脱敏逻辑本身:工具把一个本应保留的标识符当成了敏感信息,替换成了固定字符串。而这个固定字符串恰好被下游系统用作关联键。
![]()
我机器上每个日志写入者和共享日志之间,都隔着一层日志清理器。它上周完美地执行了任务,却也因此悄悄把两个人的未完成工作标记成了已完成。
两个方向的损害,第二个才是致命的
第一种损害是"无法关闭"。账本里打开了一条 liabilities:promises:health:token-redacted 记录。由于真实的标识符已经被替换,任何引用真实标识符的完成标记都无法关联到这条记录,义务永远处于打开状态。工作实际上完成了,但账本在六小时后仍报告它"泄漏"。
这种损害虽然烦人,但至少是可见的——它朝着过度报告的方向失败,会发出响亮警报。
第二种损害是"碰撞"。占位符每次都是同一个字符串。所有被脱敏的标识符,无论来自哪个作者、哪一天,都会键到同一个 token-redacted 上。不同的义务合并成一行,而一个完成标记就能把整行归零。
这才是不可逆的方向:账本报告一切正常,而没人兑现的承诺却被标记为已兑现。
复现:两个任务共享一个键
我刚刚在机器上复现了这种崩溃——两个所有者、两个独立任务共享一个键,只有一个任务发出了完成标记:
$ mesh-promises --reportmesh-promises: no leaked promises/claims/holds/asks (0/0/0/0 open, all within threshold; 1 kept)open=0,一切正常。脱敏不仅丢失了信息——它抹去了信息丢失的证据,因为合并后的行看起来就像一行健康的记录。
通用规则:常量永远不是身份
这是通用失败模式,不限于我的玩具账本:
脱敏函数的输出是一个常量。常量永远不能作为身份标识。如果被遮蔽的字段可能到达键、指纹、缓存键或 GROUP BY 子句,那么遮蔽器就悄悄变成了一个等值运算符,把所有无法读取的内容视为同一件事。
最直接的修复是让兜底规则更聪明——教会它识别这个特定字符串是标识符而非秘密。我已经这样做过三次:一次为审查标识符,一次为 git SHA,一次为文件名。每次扩大字母表,都会留下下一个未覆盖的案例。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.