Object deserialization in Reverb leading to RCE
Description
A use-after-free vulnerability in Reverb's VARIANT tensor unpacking allows attackers to overwrite vtable pointers and gain arbitrary code execution via unauthenticated gRPC endpoints.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A use-after-free vulnerability in Reverb's VARIANT tensor unpacking allows attackers to overwrite vtable pointers and gain arbitrary code execution via unauthenticated gRPC endpoints.
Vulnerability
Overview
A use-after-free vulnerability exists in Google DeepMind's Reverb, a data storage system designed for machine learning research [1]. The flaw resides in how Reverb handles the VARIANT datatype, which is meant to represent arbitrary C++ objects within tensors. When a tensor proto of type VARIANT is unpacked, memory is first allocated to store the entire tensor, and a constructor is called on each instance. Afterwards, Reverb copies the content from tensor_content into the pre-allocated memory, overwriting the vtable pointers of all previously allocated objects [2][4]. This creates a use-after-free condition where dereferencing these corrupted objects can redirect control flow.
Attack
Surface and Exploitation
Reverb exposes two unauthenticated gRPC endpoints: InsertStream and SampleStream, with no authentication or authorization by default [4]. An attacker can exploit this by inserting a crafted stream containing a malicious VARIANT tensor into the server's database via InsertStream. When a client subsequently calls SampleStream, the server unpacks the tensor into RAM, triggering the memory corruption. At this point, any method called on the corrupted object—including its destructor—allows the attacker to hijack the Program Counter [2][4].
Impact
Successful exploitation grants the attacker arbitrary code execution on the Reverb server with the privileges of the server process. Given that Reverb is often used in distributed reinforcement learning pipelines, this could lead to full compromise of the training infrastructure, data exfiltration, or further lateral movement.
Mitigation
The vulnerability has been fixed in commit 6a0dcf4 (tagged as a security patch) [3]. The fix disallows compression and decompression of non-scalar types, including DT_VARIANT and DT_RESOURCE, by adding an explicit IsSupported check in the compression path [3]. All users should upgrade to a version containing this commit or ensure that the endpoints are secured with appropriate authentication and access controls.
- GitHub - google-deepmind/reverb: Reverb is an efficient and easy-to-use data storage and transport system designed for machine learning research
- NVD - CVE-2024-8375
- Only support compression/decompression of scalar types, disallowing v… · google-deepmind/reverb@6a0dcf4
- Vulnerability in Reverb object deserialization
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
dm-reverbPyPI | <= 0.14.0 | — |
dm-reverb-nightlyPyPI | <= 0.15.0.dev20240214 | — |
Affected products
3- ghsa-coords2 versions
<= 0.14.0+ 1 more
- (no CPE)range: <= 0.14.0
- (no CPE)range: <= 0.15.0.dev20240214
- Range: 0
Patches
16a0dcf4c9e84Only support compression/decompression of scalar types, disallowing variant and resource dtypes.
3 files changed · +77 −0
reverb/cc/BUILD+1 −0 modified@@ -67,6 +67,7 @@ reverb_cc_test( deps = [ ":tensor_compression", "//reverb/cc/testing:tensor_testutil", + "//third_party/absl/status", ] + reverb_tf_deps(), )
reverb/cc/tensor_compression.cc+47 −0 modified@@ -18,6 +18,7 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" +#include "absl/strings/str_cat.h" #include "reverb/cc/platform/logging.h" #include "reverb/cc/platform/snappy.h" #include "tensorflow/core/framework/register_types.h" @@ -55,6 +56,40 @@ tensorflow::Tensor DeltaEncode(const tensorflow::Tensor& tensor, bool encode) { return output; } +bool IsSupported(const tensorflow::DataType data_type) { + switch (data_type) { + case tensorflow::DT_FLOAT: + case tensorflow::DT_DOUBLE: + case tensorflow::DT_INT32: + case tensorflow::DT_UINT8: + case tensorflow::DT_INT16: + case tensorflow::DT_INT8: + case tensorflow::DT_STRING: + case tensorflow::DT_COMPLEX64: + case tensorflow::DT_INT64: + case tensorflow::DT_BOOL: + case tensorflow::DT_QINT8: + case tensorflow::DT_QUINT8: + case tensorflow::DT_QINT32: + case tensorflow::DT_BFLOAT16: + case tensorflow::DT_QINT16: + case tensorflow::DT_QUINT16: + case tensorflow::DT_UINT16: + case tensorflow::DT_COMPLEX128: + case tensorflow::DT_HALF: + // DT_RESOURCE and DT_VARIANT are not supported. + case tensorflow::DT_UINT32: + case tensorflow::DT_UINT64: + case tensorflow::DT_FLOAT8_E5M2: + case tensorflow::DT_FLOAT8_E4M3FN: + case tensorflow::DT_INT4: + case tensorflow::DT_UINT4: + return true; + default: + return false; + } +} + } // namespace tensorflow::Tensor DeltaEncode(const tensorflow::Tensor& tensor, bool encode) { @@ -83,6 +118,12 @@ std::vector<tensorflow::Tensor> DeltaEncodeList( absl::Status CompressTensorAsProto(const tensorflow::Tensor& tensor, tensorflow::TensorProto* proto) { + if (!IsSupported(tensor.dtype())) { + return absl::InvalidArgumentError(absl::StrCat( + "Tensor of dtype ", tensorflow::DataTypeString(tensor.dtype()), + " is not supported for compression.")); + } + if (tensor.dtype() == tensorflow::DT_STRING) { tensor.AsProtoTensorContent(proto); return absl::OkStatus(); @@ -97,6 +138,12 @@ absl::Status CompressTensorAsProto(const tensorflow::Tensor& tensor, absl::StatusOr<tensorflow::Tensor> DecompressTensorFromProto( const tensorflow::TensorProto& proto) { + if (!IsSupported(proto.dtype())) { + return absl::InvalidArgumentError(absl::StrCat( + "Tensor of dtype ", tensorflow::DataTypeString(proto.dtype()), + " is not supported for decompression.")); + } + if (proto.dtype() == tensorflow::DT_STRING) { tensorflow::Tensor tensor; REVERB_CHECK(tensor.FromProto(proto));
reverb/cc/tensor_compression_test.cc+29 −0 modified@@ -18,19 +18,24 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/status/status.h" #include "reverb/cc/testing/tensor_testutil.h" #include "tensorflow/core/framework/register_types.h" #include "tensorflow/core/framework/tensor.h" #include "tensorflow/core/framework/tensor.pb.h" #include "tensorflow/core/framework/tensor_shape.h" #include "tensorflow/core/framework/types.h" #include "tensorflow/core/framework/types.pb.h" +#include "tensorflow/core/framework/variant.h" #include "tensorflow/core/platform/tstring.h" namespace deepmind { namespace reverb { namespace { +using ::testing::HasSubstr; +using ::testing::status::StatusIs; + template <typename T> void EncodeMatchesDecodeT() { tensorflow::Tensor tensor(tensorflow::DataTypeToEnum<T>::v(), @@ -103,6 +108,30 @@ TEST(TensorCompressionTest, NonStringTensorWithDeltaEncoding) { test::ExpectTensorEqual<int>(tensor, DeltaEncode(result, false)); } +TEST(TensorCompressionTest, CompressingVariantNotSupported) { + tensorflow::Tensor tensor(tensorflow::DT_VARIANT, + tensorflow::TensorShape({})); + + tensorflow::Tensor internal(tensorflow::DT_FLOAT, + tensorflow::TensorShape({2, 2})); + internal.flat<float>().setRandom(); + tensor.flat<tensorflow::Variant>()(0) = internal; + + tensorflow::TensorProto proto; + EXPECT_THAT(CompressTensorAsProto(DeltaEncode(tensor, true), &proto), + StatusIs(absl::StatusCode::kInvalidArgument, + HasSubstr("variant is not supported"))); +} + +TEST(TensorCompressionTest, DecompressingVariantNotSupported) { + tensorflow::TensorProto proto; + proto.set_dtype(tensorflow::DT_VARIANT); + + EXPECT_THAT(DecompressTensorFromProto(proto), + StatusIs(absl::StatusCode::kInvalidArgument, + HasSubstr("variant is not supported"))); +} + } // namespace } // namespace reverb } // namespace deepmind
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4News mentions
0No linked articles in our index yet.