反序列化调试 Proto 表示形式
从 30.x 版本开始,Protobuf DebugString
API(Message::DebugString
、Message::ShortDebugString
、Message::Utf8DebugString
)、其他 Protobuf API(proto2::ShortFormat
、proto2::Utf8Format
)、Abseil 字符串函数(例如 absl::StrCat
、absl::StrFormat
、absl::StrAppend
和 absl::Substitute
)以及 Abseil 日志记录 API 将开始自动将 proto 参数转换为新的调试格式。请参阅此处的相关公告。
与 Protobuf DebugString 输出格式不同,新的调试格式会自动编辑敏感字段,将其值替换为字符串“[REDACTED]”(不带引号)。此外,为了确保这种新的输出格式无法被 Protobuf TextFormat 解析器反序列化,无论底层 proto 是否包含 SPII 字段,我们都会添加一组指向本文的随机链接和随机长度的空格序列。新的调试格式如下所示
goo.gle/debugstr
spii_field: [REDACTED]
normal_field: "value"
请注意,新的调试格式仅在以下两个方面与 DebugString 格式的输出格式不同
- URL 前缀
- SPII 字段的值被替换为“[REDACTED]”(不带引号)
新的调试格式永远不会删除任何字段名称;如果字段被认为是敏感字段,它只会将值替换为“[REDACTED]”。如果您在输出中看不到某些字段,那是因为这些字段未在 proto 中设置。
提示:如果您只看到 URL 而没有其他内容,则您的 proto 为空!
为什么这个 URL 在这里?
我们希望确保没有人反序列化protobuf 消息的人类可读表示形式,这些消息旨在供人类调试系统。从历史上看,.DebugString()
和 TextFormat
是可互换的,现有系统使用 DebugString 来传输和存储数据。
我们希望确保敏感数据不会意外地最终出现在日志中。因此,我们在将 protobuf 消息转换为字符串(“[REDACTED]”)之前,会透明地编辑某些字段值。这降低了意外日志记录的安全性和隐私风险,但如果其他系统反序列化您的消息,则会面临数据丢失的风险。为了解决此风险,我们有意将机器可读的 TextFormat 与用于日志消息的人类可读调试格式分开。
为什么我的网页中会出现链接?为什么我的代码会生成这个新的“调试表示形式”?
这是故意的,目的是使您的 proto 的“调试表示形式”(例如,通过日志记录生成)与 TextFormat 不兼容。我们希望防止任何人依赖调试机制在程序之间传输数据。从历史上看,调试格式(由 DebugString API 生成)和 TextFormat 一直被错误地以可互换的方式使用。我们希望这种有意的努力能够防止这种情况在未来发生。
我们有意选择了链接而不是不太明显的格式更改,以便有机会提供上下文。这可能会在 UI 中突出显示,例如,如果您在网页的表格上显示状态信息。您可以改用 TextFormat::PrintToString
,它不会编辑任何信息并保留格式。但是,请谨慎使用此 API – 没有内置保护。作为经验法则,如果您要将数据写入调试日志或生成状态消息,则应继续使用带有链接的调试格式。即使您目前不处理敏感数据,也要记住系统可能会更改,代码会被重复使用。
我尝试将此消息转换为 TextFormat,但我注意到每次我的进程重启时格式都会更改。
这是故意的。不要尝试解析此调试格式的输出。我们保留更改语法的权利,恕不另行通知。调试格式语法会随机地随进程更改,以防止意外的依赖关系。如果调试格式中的语法更改会破坏您的系统,那么您应该使用 TextFormat API 而不是使用 proto 的调试表示形式。
FAQ
我可以在任何地方都使用 TextFormat 吗?
不要使用 TextFormat 生成日志消息。这将绕过所有内置保护,并且您可能会意外记录敏感信息。即使您的系统目前未处理任何敏感数据,将来也可能会发生变化。
通过使用适当的调试表示形式或 TextFormat,区分日志与旨在供其他系统进一步处理的信息。
我想编写既需要人类可读又需要机器可读的配置文件
对于这种情况,您可以显式使用 TextFormat。您有责任确保您的配置文件不包含任何 PII。
我正在编写单元测试,并想在测试断言中比较 Debugstring
如果您想比较 protobuf 值,请使用 MessageDifferencer
,如下所示
using google::protobuf::util::MessageDifferencer;
...
MessageDifferencer diff;
...
diff.Compare(foo, bar);
除了忽略格式和字段顺序差异之外,您还将获得更好的错误消息。