CVE-2020-28975 (published 2020-11-21T21:15Z)

svm_predict_values in svm.cpp in Libsvm v324, as used in scikit-learn 0.23.2 and other products, allows attackers to cause a denial of service (segmentation fault) via a crafted model SVM (introduced via pickle, json, or any other model permanence standard) with a large value in the _n_support array. NOTE: the scikit-learn vendor's position is that the behavior can only occur if the library's API is violated by an application that changes a private attribute.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/scikit-learn/scikit-learn
commit_details: repo_url: https://github.com/scikit-learn/scikit-learn
author: Thomas J. Fan
author_date: 2021-10-20 08:30:06-04:00
msg: FIX Prevents segfault in SVC when internals are altered (#21336)

Co-authored-by: Guillaume Lemaitre <g.lemaitre58@gmail.com>
Co-authored-by: Jérémie du Boisberranger <34657725+jeremiedbb@users.noreply.github.com>
Co-authored-by: Olivier Grisel <olivier.grisel@gmail.com>
repository: repo_url: https://github.com/scikit-learn/scikit-learn
repo_name: scikit-learn/scikit-learn
description: scikit-learn: machine learning in Python
repo_language: Python
owner: scikit-learn
file_changes: filename: v1.0.rst
change_type: ModificationType.MODIFY
diff: @@ -67,6 +67,15 @@ Fixed models
   names out from one step of a pipeline to the next. :pr:`21351` by
   `Thomas Fan`_.
 
+:mod:`sklearn.svm`
+..................
+
+- |Fix| :class:`svm.SVC` and :class:`svm.SVR` check for an inconsistency
+  in its internal representation and raise an error instead of segfaulting.
+  This fix also resolves
+  `CVE-2020-28975 <https://nvd.nist.gov/vuln/detail/CVE-2020-28975>`__.
+  :pr:`21336` by `Thomas Fan`_.
+
 .. _changes_1_0:
 
 Version 1.0.0

programming_language: Markdown
filename: _base.py
change_type: ModificationType.MODIFY
diff: @@ -616,6 +616,13 @@ class BaseLibSVM(BaseEstimator, metaclass=ABCMeta):
                     "the number of samples at training time"
                     % (X.shape[1], self.shape_fit_[0])
                 )
+        # Fixes https://nvd.nist.gov/vuln/detail/CVE-2020-28975
+        # Check that _n_support is consistent with support_vectors
+        sv = self.support_vectors_
+        if not self._sparse and sv.size > 0 and self.n_support_.sum() != sv.shape[0]:
+            raise ValueError(
+                f"The internal representation of {self.__class__.__name__} was altered"
+            )
         return X
 
     @property

programming_language: Python
filename: test_svm.py
change_type: ModificationType.MODIFY
diff: @@ -1371,3 +1371,16 @@ def test_custom_kernel_not_array_input(Estimator):
     else:  # regressor
         assert_allclose(svc1.predict(data), svc2.predict(X))
         assert_allclose(svc1.predict(data), svc3.predict(K))
+
+
+def test_svc_raises_error_internal_representation():
+    """Check that SVC raises error when internal representation is altered.
+
+    Non-regression test for #18891 and https://nvd.nist.gov/vuln/detail/CVE-2020-28975
+    """
+    clf = svm.SVC(kernel="linear").fit(X, Y)
+    clf._n_support[0] = 1000000
+
+    msg = "The internal representation of SVC was altered"
+    with pytest.raises(ValueError, match=msg):
+        clf.predict(X)

programming_language: Python