GHSA-f9qc-qg88-7pq5: Rust/buffa vulnerability
The decodeunknownfield function in buffa's protobuf decoder allocated heap memory in proportion to untrusted input (unknown fields in the serialized protobuf) without enforcing an allocation budget. Any message decoded from untrusted input using code generated with preserveunknownfields=true (the default) was affected. A small, well-formed payload of nested unknown fields inside a StartGroup could trigger roughly 22× memory amplification (e.g., a 64 MiB input forcing ~1.4 GB of heap allocation), and length-delimited unknown fields could be sized arbitrarily, enabling an unauthenticated attacker to crash a process via memory exhaustion. This was reachable from the default decode APIs, since the top-level message size cap did not account for in-decode amplification.
For users of connectrpc - the DEFAULTMAXMESSAGESIZE for connectrpc is 4MiB, which limits amplification in the worst case to ~88 MiB of memory. A flood of concurrent requests with this pattern could still be used to exhaust available memory, however.
Users are advised to either set preserveunknownfields=false on their current generated code, or upgrade to 0.8.0, which enforces per-message unknown field count limits - this is configurable, with a default of 1 million unknown fields, or ~40MiB of allocation overhead per message. Users are advised to update to the latest version, which enforces per-message unknown field count limits.
Thank you to @p80n-sec for reporting this issue.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
rust/buffato a version that resolves this vulnerability.Fixed in 0.8.0 - Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Fixed in 0.8.0 - Configuration
Set preserve_unknown_fields=false on your currently generated code to prevent the buffa protobuf decoder from allocating heap memory proportional to untrusted unknown fields.
Code generated with preserve_unknown_fields=true (buffa protobuf decoder / decode APIs) preserve_unknown_fields = false - Configuration
If using upgrade to 0.8.0, keep (or reduce) the configurable per-message unknown field count limit; the default is 1 million unknown fields (about ~40MiB allocation overhead per message).
0.8.0 per-message unknown field limit (buffa protobuf decoder) unknown field count limit = 1,000,000 - Compensating control
Ensure connectrpc DEFAULT_MAX_MESSAGE_SIZE is configured to limit message size (default stated as 4MiB), which reduces worst-case amplification (to ~88MiB of memory) compared to unrestricted decoding.
Event History
Frequently Asked Questions
Which deployments are exposed to this memory-exhaustion issue?
Any application decoding untrusted protobuf input with buffa-generated code using preserve_unknown_fields=true is affected; this is the default setting. The issue is reachable through the default decode APIs because their top-level message-size cap does not limit allocation amplification during decoding.
What does an attacker need to do to trigger it?
An unauthenticated attacker needs to submit a well-formed serialized protobuf containing crafted unknown fields. Nested unknown fields in a StartGroup can cause roughly 22× memory amplification, while length-delimited unknown fields can be sized arbitrarily to exhaust process memory.
Does connectrpc's default message-size limit prevent exploitation?
No. Its 4 MiB DEFAULT_MAX_MESSAGE_SIZE limits worst-case amplification to approximately 88 MiB per request, but concurrent malicious requests can still exhaust available memory.
What mitigation is available if upgrading is not immediately possible?
Regenerate or configure current generated code with preserve_unknown_fields=false. Alternatively, upgrade to buffa 0.8.0, which enforces per-message unknown-field limits.