CVE-2022-41888: Improper Input Validation (CWE-20)
value: TensorFlow is an open source platform for machine learning. When running on GPU, `tf.image.generate_bounding_box_proposals` receives a `scores` input that must be of rank 4 but is not checked. We have patched the issue in GitHub commit cf35502463a88ca7185a99daa7031df60b3c1c98. The fix will be included in TensorFlow 2.11. We will also cherrypick this commit on TensorFlow 2.10.1, 2.9.3, and TensorFlow 2.8.4, as these are also affected and still in supported range.
CWE description: The product receives input or data, but it does
        not validate or incorrectly validates that the input has the
        properties that are required to process the data safely and
        correctly.
CVSS v3 base score: 7.5
Published: 2022-11-18T22:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: Other
Files changed: tensorflow/core/kernels/image/generate_box_proposals_op.cu.cc, tensorflow/python/kernel_tests/image_ops/BUILD, tensorflow/python/kernel_tests/image_ops/draw_bounding_box_op_test.py
Commit date: 2022-10-07 15:34:48 -0700
Commit message: Add rank checks to GenerateBoundingBoxProposals.

PiperOrigin-RevId: 479681553

Diff: diff --git a/tensorflow/core/kernels/image/generate_box_proposals_op.cu.cc b/tensorflow/core/kernels/image/generate_box_proposals_op.cu.cc
index 678bec2c15de3..8702dba16fbb8 100644
--- a/tensorflow/core/kernels/image/generate_box_proposals_op.cu.cc
+++ b/tensorflow/core/kernels/image/generate_box_proposals_op.cu.cc
@@ -310,10 +310,26 @@ class GenerateBoundingBoxProposals : public tensorflow::OpKernel {
     VLOG(1) << "Starting Compute " << name();
     const auto scores = context->input(0);
     const auto bbox_deltas = context->input(1);
     const auto image_info = context->input(2);
     const auto anchors = context->input(3);
+
+    OP_REQUIRES(context, scores.dims() == 4,
+                errors::InvalidArgument("`scores` must be rank 4 but is rank ",
+                                        scores.dims()));
+    OP_REQUIRES(
+        context, bbox_deltas.dims() == 4,
+        errors::InvalidArgument("`bbox_deltas` must be rank 4 but is rank ",
+                                bbox_deltas.dims()));
+    OP_REQUIRES(
+        context, image_info.dims() == 2,
+        errors::InvalidArgument("`image_info` must be rank 2 but is rank ",
+                                image_info.dims()));
+    OP_REQUIRES(context, anchors.dims() == 3,
+                errors::InvalidArgument("`anchors` must be rank 3 but is rank ",
+                                        anchors.dims()));
+
     const auto num_images = scores.dim_size(0);
     const auto num_anchors = scores.dim_size(3);
     const auto height = scores.dim_size(1);
     const auto width = scores.dim_size(2);
     const auto box_dim = anchors.dim_size(2) / num_anchors;
diff --git a/tensorflow/python/kernel_tests/image_ops/BUILD b/tensorflow/python/kernel_tests/image_ops/BUILD
index a2d5752a8db4d..81edb44161e40 100644
--- a/tensorflow/python/kernel_tests/image_ops/BUILD
+++ b/tensorflow/python/kernel_tests/image_ops/BUILD
@@ -94,11 +94,11 @@ tf_py_test(
         "//tensorflow/python:parsing_ops",
         "//third_party/py/numpy",
     ],
 )
 
-tf_py_test(
+cuda_py_test(
     name = "draw_bounding_box_op_test",
     size = "small",
     srcs = ["draw_bounding_box_op_test.py"],
     deps = [
         "//tensorflow/python:array_ops",
diff --git a/tensorflow/python/kernel_tests/image_ops/draw_bounding_box_op_test.py b/tensorflow/python/kernel_tests/image_ops/draw_bounding_box_op_test.py
index 91fcd9351680a..a66d8d8a9a2a1 100644
--- a/tensorflow/python/kernel_tests/image_ops/draw_bounding_box_op_test.py
+++ b/tensorflow/python/kernel_tests/image_ops/draw_bounding_box_op_test.py
@@ -14,12 +14,15 @@
 # ==============================================================================
 """Tests for draw_bounding_box_op."""
 
 import numpy as np
 
+from tensorflow.python.framework import constant_op
 from tensorflow.python.framework import dtypes
+from tensorflow.python.framework import errors
 from tensorflow.python.framework import ops
+from tensorflow.python.framework import test_util
 from tensorflow.python.ops import array_ops
 from tensorflow.python.ops import image_ops
 from tensorflow.python.ops import image_ops_impl
 from tensorflow.python.ops import math_ops
 from tensorflow.python.platform import test
@@ -129,8 +132,24 @@ class DrawBoundingBoxOpTest(test.TestCase):
     colors = np.asarray([[0.5, 0, 0.5, 1], [0.5, 0.5, 0, 1], [0.5, 0, 0, 1],
                          [0, 0, 0.5, 1]])
     self._testDrawBoundingBoxColorCycling(
         image, dtype=dtypes.half, colors=colors)
 
+  # generate_bound_box_proposals is only available on GPU.
+  @test_util.run_gpu_only()
+  def testGenerateBoundingBoxProposals(self):
+    # Op only exists on GPU.
+    with self.cached_session(use_gpu=True):
+      with self.assertRaisesRegex((ValueError, errors.InvalidArgumentError),
+                                  "must be rank 4"):
+        scores = constant_op.constant(
+            value=[[[[1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0]]]])
+        self.evaluate(
+            image_ops.generate_bounding_box_proposals(
+                scores=scores,
+                bbox_deltas=[],
+                image_info=[],
+                anchors=[],
+                pre_nms_topn=1))
 
 if __name__ == "__main__":
   test.main()

Vulnerable code: tf_py_test(
Fixed code: 
    OP_REQUIRES(context, scores.dims() == 4,
                errors::InvalidArgument("`scores` must be rank 4 but is rank ",
                                        scores.dims()));
    OP_REQUIRES(
        context, bbox_deltas.dims() == 4,
        errors::InvalidArgument("`bbox_deltas` must be rank 4 but is rank ",
                                bbox_deltas.dims()));
    OP_REQUIRES(
        context, image_info.dims() == 2,
        errors::InvalidArgument("`image_info` must be rank 2 but is rank ",
                                image_info.dims()));
    OP_REQUIRES(context, anchors.dims() == 3,
                errors::InvalidArgument("`anchors` must be rank 3 but is rank ",
                                        anchors.dims()));

cuda_py_test(
from tensorflow.python.framework import constant_op
from tensorflow.python.framework import errors
from tensorflow.python.framework import test_util
  # generate_bound_box_proposals is only available on GPU.
  @test_util.run_gpu_only()
  def testGenerateBoundingBoxProposals(self):
    # Op only exists on GPU.
    with self.cached_session(use_gpu=True):
      with self.assertRaisesRegex((ValueError, errors.InvalidArgumentError),
                                  "must be rank 4"):
        scores = constant_op.constant(
            value=[[[[1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0]]]])
        self.evaluate(
            image_ops.generate_bounding_box_proposals(
                scores=scores,
                bbox_deltas=[],
                image_info=[],
                anchors=[],
                pre_nms_topn=1))