反序列化调试 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 已被错误地互换使用。我们希望这一有意的工作能够阻止这种情况的发生。
我们特意选择了一个链接而不是不那么明显的格式更改,以便有机会提供上下文。这可能会在用户界面中显得突出,例如,如果您在网页表格中显示状态信息。您可以改用 TextFormat::PrintToString,它不会编辑任何信息并保留格式。但是,请谨慎使用此 API——它没有内置的保护措施。根据经验,如果您正在将数据写入调试日志或生成状态消息,则应继续使用带有链接的调试格式。即使您目前没有处理敏感数据,也要记住系统可能会更改并且代码会被重用。
我尝试将此消息转换为 TextFormat,但我注意到每次进程重启时格式都会改变。
这是有意为之的。请勿尝试解析此调试格式的输出。我们保留更改语法的权利,恕不另行通知。调试格式的语法会随进程随机更改,以防止无意中产生依赖。如果调试格式的语法更改会破坏您的系统,则您很可能应该使用 TextFormat API,而不是使用 proto 的调试表示。
常见问题解答
我可以到处都使用 TextFormat 吗?
请勿使用 TextFormat 生成日志消息。这将绕过所有内置保护,您可能会意外记录敏感信息。即使您的系统目前没有处理任何敏感数据,这种情况也可能在将来发生变化。
通过酌情使用调试表示或 TextFormat,将日志与用于其他系统进一步处理的信息区分开来。
我希望编写既可读又可机器读取的配置文件
对于此用例,您可以显式使用 TextFormat。您有责任确保您的配置文件不包含任何 PII。
我正在编写单元测试,并且希望在测试断言中比较 Debugstring
如果要比较 protobuf 值,请使用 MessageDifferencer,如下所示:
using google::protobuf::util::MessageDifferencer;
...
MessageDifferencer diff;
...
diff.Compare(foo, bar);
除了忽略格式和字段顺序的差异外,您还将获得更好的错误消息。