ONNX external_data offset field accepted without bounds validation β PoC
Summary
ONNX TensorProto.external_data allows a model to declare an arbitrary byte offset into an external binary weight file. onnx.checker.check_model() (including full_check=True) accepts the model without validating whether the declared offset actually points to the tensor's intended data region. onnxruntime.InferenceSession reads at the declared offset, loading values from an arbitrary region of the file. A user inspecting the external weight file from byte 0 sees benign values. No warning is emitted at any stage.
Affected versions
- onnx 1.21.0
- onnxruntime 1.23.2
- Python 3.10 / aarch64 Ubuntu 22.04
Reproduction
pip install onnx onnxruntime numpy
python poc.py
Expected output:
=== ONNX external_data offset opacity PoC ===
ββ Artifact ββββββββββββββββββββββββββββββββββββββ
weights.bin[0:4] = 1.0 β naive inspection sees benign value
weights.bin[4:8] = 999.0 β hidden malicious value at offset 4
model.onnx external_data: offset=4 β points into malicious region
ββ Inspection (onnx.checker) ββββββββββββββββββββββ
check_model(model_path) β PASS β
check_model(model_path, full_check=True) β PASS β
ββ Runtime (ORT InferenceSession) ββββββββββββββββ
Input X = 2.0
ORT output Y = 1998.0 (= 999.0 Γ 2.0)
Warning emitted (stderr): NONE
Warning emitted (Python): NONE
ββ Output flip ββββββββββββββββββββββββββββββββββββ
BENIGN_EXPECTED (weights.bin[0:4]=1.0 Γ X=2.0): 2.0
MALICIOUS_ACTUAL (ORT via offset=4 β 999.0 Γ 2.0): 1998.0
OUTPUT_FLIP_CONFIRMED: True
β PoC PASS: checker accepts; runtime uses malicious offset; no warning.
Gap description
ONNX TensorProto can declare external weight data via the external_data key-value list. The offset key specifies the byte offset within the external file from which the tensor's data begins. The ONNX checker does not validate that this offset corresponds to the region the model author declared β it only validates that the external_data structure is syntactically valid. A crafted model can set offset=N to point into any region of the external binary file, including regions that contain values different from what a naive byte-0 inspection would reveal.
The external binary file (weights.bin) in this PoC contains:
- Bytes 0β3: float32
1.0(benign β visible to a user inspecting from the start of the file) - Bytes 4β7: float32
999.0(malicious β loaded by ORT via the declaredoffset=4)
The model's external_data declares offset=4, causing ORT to read the malicious value. The checker passes both with and without full_check=True. No warning is emitted.
Non-claims
- Does not enable code execution of any kind
- Does not involve unsafe deserialization (no p1ckle/eval/exec)
- Does not involve out-of-bounds memory access or native crashes
- Does not involve directory traversal in the file path
- Impact is limited to data addressing opacity (weight value substitution)
Files
| File | Description |
|---|---|
model.onnx |
Crafted ONNX model with external_data offset=4 |
weights.bin |
External weight file (benign at offset 0, malicious at offset 4) |
poc.py |
End-to-end PoC: builds artifact, runs checker and ORT, confirms output flip |
build_poc.py |
Standalone artifact builder |