CVE-2022-35993: Reachable Assertion (CWE-617)
value: TensorFlow is an open source platform for machine learning. When `SetSize` receives an input `set_shape` that is not a 1D tensor, it gives a `CHECK` fails that can be used to trigger a denial of service attack. We have patched the issue in GitHub commit cf70b79d2662c0d3c6af74583641e345fc939467. The fix will be included in TensorFlow 2.10.0. We will also cherrypick this commit on TensorFlow 2.9.1, TensorFlow 2.8.1, and TensorFlow 2.7.2, as these are also affected and still in supported range. There are no known workarounds for this issue.
CWE description: The product contains an assert() or similar statement that can be triggered by an attacker, which leads to an application exit or other behavior that is more severe than necessary.
CVSS v3 base score: 7.5
Published: 2022-09-16T23:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: Python
Files changed: tensorflow/core/kernels/set_kernels.cc, tensorflow/python/kernel_tests/math_ops/sets_test.py
Commit date: 2022-07-13 10:02:58 -0700
Commit message: Fix tf.raw_ops.SetSize vulnerability with invalid input arg specifying shape.

Check that given input is a 1D tensor, as required.

PiperOrigin-RevId: 460740463

Diff: diff --git a/tensorflow/core/kernels/set_kernels.cc b/tensorflow/core/kernels/set_kernels.cc
index 5c6170f918822..3570e6229f634 100644
--- a/tensorflow/core/kernels/set_kernels.cc
+++ b/tensorflow/core/kernels/set_kernels.cc
@@ -68,12 +68,16 @@ Status GroupShape(const VarDimArray& input_shape, ShapeArray* grouped_shape) {
 Status SparseTensorFromContext(OpKernelContext* ctx, const int32_t base_index,
                                const bool validate_indices,
                                sparse::SparseTensor* tensor) {
   // Assume row-major order.
   TensorShape shape;
-  TF_RETURN_IF_ERROR(TensorShape::BuildTensorShape(
-      ctx->input(base_index + 2).vec<int64_t>(), &shape));
+  const Tensor& shape_tensor = ctx->input(base_index + 2);
+  if (shape_tensor.dims() != 1) {
+    return errors::InvalidArgument("Shape must be a 1D tensor.");
+  }
+  TF_RETURN_IF_ERROR(
+      TensorShape::BuildTensorShape(shape_tensor.vec<int64_t>(), &shape));
   CheckRankAtLeast2(ctx, shape);
   std::vector<int64_t> order(shape.dims());
   std::iota(order.begin(), order.end(), 0);
 
   Status status = sparse::SparseTensor::Create(
diff --git a/tensorflow/python/kernel_tests/math_ops/sets_test.py b/tensorflow/python/kernel_tests/math_ops/sets_test.py
index 61a11606e661e..a35214173d59b 100644
--- a/tensorflow/python/kernel_tests/math_ops/sets_test.py
+++ b/tensorflow/python/kernel_tests/math_ops/sets_test.py
@@ -21,10 +21,11 @@ from tensorflow.python.framework import constant_op
 from tensorflow.python.framework import dtypes
 from tensorflow.python.framework import errors_impl
 from tensorflow.python.framework import sparse_tensor as sparse_tensor_lib
 from tensorflow.python.framework import test_util
 from tensorflow.python.ops import array_ops
+from tensorflow.python.ops import gen_set_ops
 from tensorflow.python.ops import math_ops
 from tensorflow.python.ops import sets
 from tensorflow.python.ops import sparse_ops
 from tensorflow.python.platform import googletest
 
@@ -1301,8 +1302,20 @@ class SetOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase):
                          [1, 2], [1, 3], [1, 4], [2, 0], [3, 0], [3, 1]])
     self.assertAllEqual(
         result.values,
         _constant([1, 3, 5, 7, 9, 0, 2, 4, 5, 6, 6, 8, 9], dtype))
 
+  def test_raw_ops_setsize_invalid_shape(self):
+    with self.assertRaisesRegex(errors_impl.InvalidArgumentError,
+                                "Shape must be a 1D tensor"):
+      invalid_shape = 1
+      self.evaluate(
+          gen_set_ops.set_size(
+              set_indices=1,
+              set_values=[1, 1],
+              set_shape=invalid_shape,
+              validate_indices=True,
+              name=""))
+
 
 if __name__ == "__main__":
   googletest.main()

Vulnerable code:   TF_RETURN_IF_ERROR(TensorShape::BuildTensorShape(
      ctx->input(base_index + 2).vec<int64_t>(), &shape));
Fixed code:   const Tensor& shape_tensor = ctx->input(base_index + 2);
  if (shape_tensor.dims() != 1) {
    return errors::InvalidArgument("Shape must be a 1D tensor.");
  }
  TF_RETURN_IF_ERROR(
      TensorShape::BuildTensorShape(shape_tensor.vec<int64_t>(), &shape));
from tensorflow.python.ops import gen_set_ops
  def test_raw_ops_setsize_invalid_shape(self):
    with self.assertRaisesRegex(errors_impl.InvalidArgumentError,
                                "Shape must be a 1D tensor"):
      invalid_shape = 1
      self.evaluate(
          gen_set_ops.set_size(
              set_indices=1,
              set_values=[1, 1],
              set_shape=invalid_shape,
              validate_indices=True,
              name=""))