YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
ONNX External Data Hardlink Runtime Mismatch PoC
This is a benign security research PoC for ONNX external-data handling. It does not execute code, make network connections, or access credentials. The marker payload is the ASCII string ONNX_EXTERNAL_DATA_MARKER_v1.
Status
This package demonstrates a runtime/parser mismatch in ONNX external-data hardlink handling:
onnx==1.21.0blocks direct traversal and hardlink external-data paths.onnxruntime==1.26.0blocks direct..traversal but loads an external-data file that is a hardlink.modelscan==0.8.8does not scan.onnxfiles in this test and reportstotal_scanned: 0.
The strongest portable artifact is archives/in_archive_hardlink.tar: after extraction, model_dir/data/hardlink_marker.bin is a hardlink. onnx.load() rejects the extracted model, while ONNX Runtime loads it and returns the marker. This is still target-dependent because it requires a workflow that accepts or extracts ONNX model tarballs before calling ONNX Runtime.
Files
make_poc.py- creates the benign external-data models and marker files.verify_poc.py- recreates artifacts and validates ONNX, ONNX Runtime, and ModelScan behavior.verify_tar_package.py- creates and validates tar package variants, including the in-archive hardlink case.archives/in_archive_hardlink.tar- portable tar archive containing an ONNX model and an in-archive hardlink external data file.model_dir/valid_external.onnx- valid ONNX model whose tensor data is inside the model directory.model_dir/traversal_external.onnx- model whose external tensor path uses../outside/outside_marker.bin.model_dir/hardlink_external.onnx- model whose external tensor path points todata/hardlink_marker.bin.manifest.json- artifact hashes from the local generation run.results.json- validation results from the local run.tar_results.json- archive validation results from the local run.modelscan_model_dir.json- ModelScan directory scan output.
Reproduction: Direct External Data
python -m venv .venv
.\.venv\Scripts\python -m pip install -r .\requirements.txt
.\.venv\Scripts\python .\verify_poc.py
Expected behavior on the tested Windows host:
valid_external.onnxloads in both ONNX and ONNX Runtime and outputsONNX_EXTERNAL_DATA_MARKER_v1.traversal_external.onnxis blocked by both ONNX and ONNX Runtime.hardlink_external.onnxis blocked by ONNX but loaded by ONNX Runtime, returningONNX_EXTERNAL_DATA_MARKER_v1.
Reproduction: Tar Package
.\.venv\Scripts\python .\verify_tar_package.py
Expected behavior on the tested Windows host:
in_archive_hardlink.tarextracts under both plaintarfile.extractall()andonnx.utils._extract_model_safe().- The extracted
model_dir/data/hardlink_marker.binhasnlink: 2. onnx.load()rejects the extractedmodel_dir/hardlink_external.onnx.onnxruntime.InferenceSession()loads the same extracted model and outputsONNX_EXTERNAL_DATA_MARKER_v1.- Absolute and relative hardlinks to files outside the extraction destination are blocked by ONNX's Python 3.12
datafilter path.
Tested Versions
- Python 3.12.12
- ONNX 1.21.0
- ONNX Runtime 1.26.0
- ModelScan 0.8.8
Artifact Hashes
valid_external.onnx f5f2fca62636df523607d8c86deb6fa4b49220895afb222d743930c91230126a
traversal_external.onnx 3baaa475986d1b18a717909c8becfd27947bed7925fd79cefc586224f50d8b97
hardlink_external.onnx 1fbc093d15a175d37972dea47c26099beb2d91b37bd0e3a010f53fd212b0ec51
marker data 8878d9c0b5eca6c97c5d6e019bd6616ba8aa664a13722c533b273de593325c8e
in_archive_hardlink.tar de563c4692d0e0a5ea015385ba37cb7e3b9253c059f4b65a9b8b20e27e0fbbb3
Impact and Limitations
Impact shown locally: external data can be consumed by ONNX Runtime through a hardlink path that the ONNX Python loader rejects as a hardlink attack. In workflows that treat a model tarball as a trusted model directory after extraction, the runtime can consume file contents through hardlink state that ONNX's own loader considers unsafe.
Limitations:
- This is not ACE.
- The in-archive hardlink case demonstrates boundary/parity mismatch, not arbitrary host-file read.
- Arbitrary host-file read requires a separate unsafe extractor that creates hardlinks to existing files outside the extraction root; ONNX's current Python 3.12 safe extraction path blocks those external-link variants.
- The issue is most relevant to services or examples that download/extract ONNX model tarballs and then load the extracted model with ONNX Runtime.
Mitigation
Runtime loaders should apply the same external-data hardlink rejection used by current ONNX Python loading: reject external data files whose link count indicates multiple hardlinks, and keep canonical path containment checks for direct traversal and symlinks.