ONNX Runtime External Data Hardlink Mismatch PoC

Benign security proof-of-concept for an ONNX external-data scanner/runtime mismatch.

Summary

ONNX 1.21.0 rejects this model package because the external initializer file has multiple hard links, indicating a hardlink attack. ONNX Runtime 1.26.0 loads the same model with default InferenceSession(...) and returns bytes from the hardlinked external initializer.

The model-controlled external-data location is a normal relative filename:

weights.bin

The package supplies model_dir/weights.bin as a hardlink to outside_dir/marker.bin. This demonstrates that ONNX Runtime's external-data path validation rejects path escapes and symlinks, but does not enforce ONNX's hardlink protection before reading external initializer data.

Tested Versions

  • onnx==1.21.0
  • onnxruntime==1.26.0
  • modelscan==0.8.8
  • Python 3.12.3
  • Linux filesystem with hardlink support

Files

  • onnx_ort_hardlink_case.tar: PoC package preserving the hardlink relationship.
  • verify_poc.py: Extracts the tar, verifies hardlink metadata, then compares ONNX and ONNX Runtime behavior.
  • make_poc.py: Rebuilds the PoC package files from scratch.
  • requirements.txt: Tested dependency versions.

The tar archive contains:

model_dir/poc_ort_hardlink.onnx
model_dir/weights.bin
outside_dir/marker.bin  hardlink to model_dir/weights.bin

Reproduce

python -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt

python verify_poc.py

Expected result:

  • hardlink_same_inode: true
  • hardlink_count: 2
  • onnx_checker.returncode: non-zero
  • onnx_load.returncode: non-zero
  • onnxruntime_file.stdout: ONNX_ORT_HARDLINK_READ
  • onnxruntime_absolute.stdout: ONNX_ORT_HARDLINK_READ
  • onnxruntime_bytes_with_folder.stdout: ONNX_ORT_HARDLINK_READ
  • impact: onnx_checker_rejects_hardlink_but_onnxruntime_reads_marker

ModelScan 0.8.8 does not support .onnx and skips the file, so the main claim is the ONNX checker/runtime mismatch, not a ModelScan ONNX bypass.

Artifact Hashes

b42c0c8d2de4848d40e2b579d9780050a6d9d95b1bc09a8721d974a46eb25ea3  onnx_ort_hardlink_case.tar
a2c3b161e77dda12f515fc76586df4a995e2ebb6c74876cbc24b68fca7df235b  model_dir/poc_ort_hardlink.onnx
ecccfc04eb086689b520680edb4ab2d9efb8e82abe67c00bef6a160c0ec0599e  model_dir/weights.bin
ecccfc04eb086689b520680edb4ab2d9efb8e82abe67c00bef6a160c0ec0599e  outside_dir/marker.bin

Impact

A pipeline can validate or preflight an ONNX model with ONNX 1.21.0 and correctly reject hardlinked external data, while a deployment path using ONNX Runtime 1.26.0 still loads the model and reads the hardlinked bytes. The demonstrated impact is local file read through ONNX external-data hardlink handling under normal hardlink filesystem constraints.

This PoC is benign: the external data is a controlled marker string, and no shell commands, credential access, persistence, or network activity are used.

Limitations

  • Not remote code execution.
  • Requires a filesystem/package path that can preserve or recreate hardlinks.
  • Hardlink attacks usually require the linked file to be on the same filesystem and accessible to the attacker at package construction time.
  • The report should be framed as an ONNX Runtime external-data hardlink isolation gap and checker/runtime mismatch, not as a string path traversal.

Suggested Mitigation

Mirror ONNX's external-data hardlink protections in ONNX Runtime. Reject external data files with link count greater than one, ideally after opening the file and validating the opened file descriptor, so parent directory races and hardlink substitutions are covered consistently.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support