YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
ONNX ZipMap emits probability labels inconsistent with upstream classifier labels without checker or ORT warning
Summary
A single ONNX model artifact can be constructed where a TreeEnsembleClassifier emits a label output and a downstream ZipMap emits a probability map whose top-probability key disagrees with that label. onnx.checker(full_check=True) passes without error or warning. onnxruntime.InferenceSession loads and runs the model with zero warnings. No hidden fields, no invisible protobuf entries, and no scanner bypass is claimed.
Finding
ONNX does not enforce or warn when a ZipMap operator's classlabels_strings attribute is semantically inconsistent with the classlabels_strings of an upstream classifier operator. Both attributes are explicit, visible NodeProto.attribute entries in the protobuf. However, no standard ONNX toolchain component (onnx.checker, onnx.shape_inference, or ORT InferenceSession) validates cross-operator label consistency or emits any warning when these attributes conflict.
Result for input x=0.8:
| Output | Value | Source |
|---|---|---|
| label Y | "dangerous" |
TreeEnsembleClassifier |
| prob_map | {"benign": 1.0, "dangerous": 0.0} |
ZipMap (reversed keys) |
| argmax(prob_map) | "benign" |
consumer B pattern |
| label Y == argmax(prob_map) | False |
divergence confirmed |
| onnx.checker(full_check=True) | PASS | no cross-op label check |
| ORT warnings | 0 | no warning emitted |
Scope
- No claim of hidden or invisible fields. Both
classlabels_stringsattributes are plaintextNodeProto.attributeentries visible in the protobuf graph (e.g., in Netron or viaonnx.load()). - No scanner bypass as a primary claim. The finding is the absence of cross-operator label consistency validation in the ONNX checker and ORT.
- No RCE, ACE, or memory corruption. Impact is model integrity / classification output inconsistency.
- By-design acknowledgment. The ONNX specification does not require
ZipMap.classlabels_stringsto match any upstream classifier's class labels. The gap is that neither the checker nor the runtime enforces or warns about this inconsistency.
Impact
Applications that use the ZipMap probability map as their authoritative classification interface (for example, using argmax(prob_map) to determine the predicted class, or applying a per-class probability threshold) will receive results that contradict the TreeEnsembleClassifier label output, with no automated warning from the ONNX toolchain.
This pattern is consistent with how sklearn-onnx (skl2onnx) exports classifiers implementing predict_proba(): TreeEnsembleClassifier → ZipMap, where the probability map is consumed downstream as the primary class-probability interface.
Non-Claims
- No hidden field claim
- No invisible attribute claim
- No scanner bypass primary claim
- No arbitrary output manipulation claim
- No RCE or ACE
- No memory corruption
- No High / Critical / CVSS severity claim
Reproduction
pip install -r requirements.txt
python build_poc_model.py
python reproduce_label_probability_divergence.py
python inspect_graph_labels.py
python run_checker_and_ort.py
sha256sum -c SHA256SUMS.txt
Environment
| Component | Version |
|---|---|
| Python | 3.10.x |
| onnx | ≥1.14.0 |
| onnxruntime | ≥1.16.0 |
| numpy | ≥1.24.0 |
Files
| File | Description |
|---|---|
zipmap_label_probability_divergence.onnx |
PoC model artifact |
build_poc_model.py |
Builds the PoC model |
reproduce_label_probability_divergence.py |
Reproduces the divergence (10-run + 5 subprocess) |
inspect_graph_labels.py |
Shows both classlabels_strings attributes in protobuf |
run_checker_and_ort.py |
Records checker and ORT behavior |
evidence_reproducibility.json |
Reproducibility evidence |
evidence_tooling_behavior.json |
Checker and ORT toolchain behavior |
evidence_static_detectability.json |
Static detectability classification |
SHA256SUMS.txt |
SHA256 hashes for all package files |