Merge #330519: python311Packages.onnx: patch CVE-2024-5187

...into release-24.05
This commit is contained in:
Vladimír Čunát 2024-08-22 10:43:06 +02:00
commit 4ca9c8f025
No known key found for this signature in database
GPG Key ID: E747DF1F9575A3AA
2 changed files with 146 additions and 0 deletions

View File

@ -0,0 +1,145 @@
Combination of upstream 3fc3845edb048df559aa2a839e39e95503a0ee34
and 1b70f9b673259360b6a2339c4bd97db9ea6e552f, adjusted to apply
to v1.15.0
diff --git a/onnx/backend/test/runner/__init__.py b/onnx/backend/test/runner/__init__.py
index 4d9dce0b..5bab19c1 100644
--- a/onnx/backend/test/runner/__init__.py
+++ b/onnx/backend/test/runner/__init__.py
@@ -10,7 +10,6 @@ import os
import re
import shutil
import sys
-import tarfile
import tempfile
import time
import unittest
@@ -221,8 +220,7 @@ class Runner:
)
urlretrieve(model_test.url, download_file.name)
print("Done")
- with tarfile.open(download_file.name) as t:
- t.extractall(models_dir)
+ onnx.utils._extract_model_safe(download_file.name, models_dir)
except Exception as e:
print(f"Failed to prepare data for model {model_test.model_name}: {e}")
raise
diff --git a/onnx/hub.py b/onnx/hub.py
index e5ca9e2c..8c04515d 100644
--- a/onnx/hub.py
+++ b/onnx/hub.py
@@ -9,7 +9,6 @@ import hashlib
import json
import os
import sys
-import tarfile
from io import BytesIO
from os.path import join
from typing import IO, Any, Dict, List, Optional, Set, Tuple, cast
@@ -280,6 +279,7 @@ def download_model_with_test_data(
) -> Optional[str]:
"""
Downloads a model along with test data by name from the onnx model hub and returns the directory to which the files have been extracted.
+ Users are responsible for making sure the model comes from a trusted source, and the data is safe to be extracted.
:param model: The name of the onnx model in the manifest. This field is case-sensitive
:param repo: The location of the model repo in format "user/repo[:branch]".
@@ -337,12 +337,14 @@ def download_model_with_test_data(
"download the model from the model hub."
)
- with tarfile.open(local_model_with_data_path) as model_with_data_zipped:
- # FIXME: Avoid index manipulation with magic numbers
- local_model_with_data_dir_path = local_model_with_data_path[
- 0 : len(local_model_with_data_path) - 7
- ]
- model_with_data_zipped.extractall(local_model_with_data_dir_path)
+ # FIXME: Avoid index manipulation with magic numbers,
+ # remove ".tar.gz"
+ local_model_with_data_dir_path = local_model_with_data_path[
+ 0 : len(local_model_with_data_path) - 7
+ ]
+ onnx.utils._extract_model_safe(
+ local_model_with_data_path, local_model_with_data_dir_path
+ )
model_with_data_path = (
local_model_with_data_dir_path
+ "/"
diff --git a/onnx/utils.py b/onnx/utils.py
index 28624f63..e1236fb2 100644
--- a/onnx/utils.py
+++ b/onnx/utils.py
@@ -4,6 +4,7 @@
from __future__ import annotations
import os
+import tarfile
import onnx.checker
import onnx.helper
@@ -212,3 +213,65 @@ def extract_model(
onnx.save(extracted, output_path)
if check_model:
onnx.checker.check_model(output_path)
+
+
+def _tar_members_filter(
+ tar: tarfile.TarFile, base: str | os.PathLike
+) -> list[tarfile.TarInfo]:
+ """Check that the content of ``tar`` will be extracted safely
+
+ Args:
+ tar: The tarball file
+ base: The directory where the tarball will be extracted
+
+ Returns:
+ list of tarball members
+ """
+ result = []
+ for member in tar:
+ member_path = os.path.join(base, member.name)
+ abs_base = os.path.abspath(base)
+ abs_member = os.path.abspath(member_path)
+ if not abs_member.startswith(abs_base):
+ raise RuntimeError(
+ f"The tarball member {member_path} in downloading model contains "
+ f"directory traversal sequence which may contain harmful payload."
+ )
+ elif member.issym() or member.islnk():
+ raise RuntimeError(
+ f"The tarball member {member_path} in downloading model contains "
+ f"symbolic links which may contain harmful payload."
+ )
+ result.append(member)
+ return result
+
+
+def _extract_model_safe(
+ model_tar_path: str | os.PathLike, local_model_with_data_dir_path: str | os.PathLike
+) -> None:
+ """Safely extracts a tar file to a specified directory.
+
+ This function ensures that the extraction process mitigates against
+ directory traversal vulnerabilities by validating or sanitizing paths
+ within the tar file. It also provides compatibility for different versions
+ of the tarfile module by checking for the availability of certain attributes
+ or methods before invoking them.
+
+ Args:
+ model_tar_path: The path to the tar file to be extracted.
+ local_model_with_data_dir_path: The directory path where the tar file
+ contents will be extracted to.
+ """
+ with tarfile.open(model_tar_path) as model_with_data_zipped:
+ # Mitigate tarball directory traversal risks
+ if hasattr(tarfile, "data_filter"):
+ model_with_data_zipped.extractall(
+ path=local_model_with_data_dir_path, filter="data"
+ )
+ else:
+ model_with_data_zipped.extractall(
+ path=local_model_with_data_dir_path,
+ members=_tar_members_filter(
+ model_with_data_zipped, local_model_with_data_dir_path
+ ),
+ )

View File

@ -45,6 +45,7 @@ buildPythonPackage rec {
url = "https://github.com/onnx/onnx/commit/08a399ba75a805b7813ab8936b91d0e274b08287.patch";
hash = "sha256-9X92N9i/hpQjDGe4I/C+FwUcTUTtP2Nf7+pcTA2sXoA=";
})
./1.15.0-CVE-2024-5187.patch
];
nativeBuildInputs = [