CVE-2026-56676
9router: Image prefetch DNS rebinding allows SSRF to internal services
9Router is an AI router & token saver. Prior to 0.5.2, 9router validates image URLs by resolving the host before fetching, but open-sse/translator/concerns/image.js performs the later server-side image fetch with a separate DNS resolution. An authenticated attacker with access to the LLM proxy can use a vision-capable model and an attacker-controlled DNS name that first resolves to a public IP and then rebinds to an internal address, allowing server-side requests to internal-only HTTP services. This issue is fixed in version 0.5.2.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- Low
- Integrity
- Low
- Availability
- Low
Exploit likelihood
What each source reports
CVE List Score used
7.4
9router: Image prefetch DNS rebinding allows SSRF to internal services
9Router is an AI router & token saver. Prior to 0.5.2, 9router validates image URLs by resolving the host before fetching, but open-sse/translator/concerns/image.js performs the later server-side image fetch with a separate DNS resolution. An authenticated attacker with access to the LLM proxy can use a vision-capable model and an attacker-controlled DNS name that first resolves to a public IP and then rebinds to an internal address, allowing server-side requests to internal-only HTTP services. This issue is fixed in version 0.5.2.
- Record
CVE-2026-56676- CVSS 3.1
- 7.4 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:L - Weakness
- CWE-367, CWE-918
- Updated
- 2026-11-02
EUVDEUVD-2026-42929
7.4
9Router is an AI router & token saver. Prior to 0.5.2, 9router validates image URLs by resolving the host before fetching, but open-sse/translator/concerns/image.js performs the later server-side image fetch with a separate DNS resolution. An authenticated attacker with access to the LLM proxy can use a vision-capable model and an attacker-controlled DNS name that first resolves to a public IP and then rebinds to an internal address, allowing server-side requests to internal-only HTTP services. This issue is fixed in version 0.5.2.
- Record
EUVD-2026-42929- CVSS 3.1
- 7.4 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:L - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-cmhj-wh2f-9cgx
7.4
9router: Image prefetch DNS rebinding allows SSRF to internal services
Summary
9router validates image URLs by resolving the host before fetching, but the later server-side fetch performs a separate DNS resolution. An attacker-controlled DNS name can resolve to a public IP during validation and then rebind to an internal Docker/private IP during the fetch. This allows the server-side image prefetch to reach internal-only HTTP services (SSRF).
Details
- Affected version / commit: 9router
v0.4.80@b282f05. - Reachable through
/v1/chat/completionswith a vision-capable model and animage_urlcontent part. A vision-capable model name is required so the image survives modality stripping and the server-side prefetch is armed. - The provider used in this reproduction is the bundled mock provider — no real API key and no real provider call.
- internal-admin (the SSRF target) is not exposed to the host network; it is reachable only from inside the Docker network.
- rebind-dns behaviour for
rebind.9r.test:- first A response →
1.1.1.1(public) to pass the public-host guard, - second A response →
172.29.0.10(internal-admin) during the fetch.
- first A response →
- internal-admin logs
GET /ssrf-markerwithpeer=172.29.0.30(theproxied-routercontainer), proving the server-side fetch landed on the internal service. - mock-provider receives
POST /api/chatand the flow completes withHTTP 200. - Root cause: DNS TOCTOU — the IP is not pinned between the validation resolution (the public-host guard) and the fetch resolution. The guard and the fetch each resolve the hostname independently, so a TTL-0 rebinding authority can return a public IP to the guard and an internal IP to the fetch.
Proof of Concept
This repository is a self-contained Docker Compose reproduction. No real provider is called and no real API key is required.
- Build and start the stack:
docker compose up --build - Confirm
internal-adminis unreachable from the host:curl -i http://127.0.0.1:18083/ssrf-marker # connection refused / fail docker compose ps # internal-admin has NO host port mapping - Send the request named
POST image-prefetch DNS rebinding triggerfromrequests.http, or with curl:curl -i -X POST http://127.0.0.1:18082/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "ollama-local/gemma3", "messages": [{"role":"user","content":[ {"type":"text","text":"reproduction image-prefetch trigger"}, {"type":"image_url","image_url":{"url":"http://rebind.9r.test:8080/ssrf-marker?case=rebind-trigger"}} ]}], "stream": false }'
Impact
- SSRF to internal HTTP services reachable from the 9router host/container.
- Depending on the environment, this can reach cloud metadata endpoints, internal admin panels, or be used for internal service discovery.
- Blind / semi-blind SSRF when the fetched response is not returned to the attacker; an exfil variant (pointing the image at an internal endpoint that returns valid image bytes) can return internal content base64-encoded to the upstream.
- Requires a code path that prefetches/normalizes remote images for vision-capable providers.
- No real credential is needed for the reproduction.
Suggested Fix
- Pin the resolved IP after validation and connect to that IP (resolve once, then reuse the address for the fetch).
- Block private, loopback, link-local, multicast, and cloud-metadata ranges at connect time, not only at validation time.
- Perform DNS resolution and IP checks immediately before the request and against the address actually used to connect.
- Disable redirects, or re-validate every redirect target with the same checks.
- Enforce an allowlist for image-fetch domains where feasible.
- Add a timeout, a response size limit, and a content-type check.
- Record
GHSA-cmhj-wh2f-9cgx- CVSS 3.1
- 7.4 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:L - Weakness
- CWE-367, CWE-918
- Updated
- 2026-11-02
NVD
7.4
9Router is an AI router & token saver. Prior to 0.5.2, 9router validates image URLs by resolving the host before fetching, but open-sse/translator/concerns/image.js performs the later server-side image fetch with a separate DNS resolution. An authenticated attacker with access to the LLM proxy can use a vision-capable model and an attacker-controlled DNS name that first resolves to a public IP and then rebinds to an internal address, allowing server-side requests to internal-only HTTP services. This issue is fixed in version 0.5.2.
- Record
CVE-2026-56676- CVSS 3.1
- 7.4 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:L - Weakness
- CWE-367, CWE-918
- Updated
- 2026-11-02
OSV
7.4
9router: Image prefetch DNS rebinding allows SSRF to internal services
9Router is an AI router & token saver. Prior to 0.5.2, 9router validates image URLs by resolving the host before fetching, but open-sse/translator/concerns/image.js performs the later server-side image fetch with a separate DNS resolution. An authenticated attacker with access to the LLM proxy can use a vision-capable model and an attacker-controlled DNS name that first resolves to a public IP and then rebinds to an internal address, allowing server-side requests to internal-only HTTP services. This issue is fixed in version 0.5.2.
- Record
CVE-2026-56676- CVSS 3.1
- 7.4 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:L - Weakness
- CWE-367, CWE-918
- Updated
- 2026-11-02
OSVGHSA-cmhj-wh2f-9cgx
7.4
9router: Image prefetch DNS rebinding allows SSRF to internal services
Summary
9router validates image URLs by resolving the host before fetching, but the later server-side fetch performs a separate DNS resolution. An attacker-controlled DNS name can resolve to a public IP during validation and then rebind to an internal Docker/private IP during the fetch. This allows the server-side image prefetch to reach internal-only HTTP services (SSRF).
Details
- Affected version / commit: 9router
v0.4.80@b282f05. - Reachable through
/v1/chat/completionswith a vision-capable model and animage_urlcontent part. A vision-capable model name is required so the image survives modality stripping and the server-side prefetch is armed. - The provider used in this reproduction is the bundled mock provider — no real API key and no real provider call.
- internal-admin (the SSRF target) is not exposed to the host network; it is reachable only from inside the Docker network.
- rebind-dns behaviour for
rebind.9r.test:- first A response →
1.1.1.1(public) to pass the public-host guard, - second A response →
172.29.0.10(internal-admin) during the fetch.
- first A response →
- internal-admin logs
GET /ssrf-markerwithpeer=172.29.0.30(theproxied-routercontainer), proving the server-side fetch landed on the internal service. - mock-provider receives
POST /api/chatand the flow completes withHTTP 200. - Root cause: DNS TOCTOU — the IP is not pinned between the validation resolution (the public-host guard) and the fetch resolution. The guard and the fetch each resolve the hostname independently, so a TTL-0 rebinding authority can return a public IP to the guard and an internal IP to the fetch.
Proof of Concept
This repository is a self-contained Docker Compose reproduction. No real provider is called and no real API key is required.
- Build and start the stack:
docker compose up --build - Confirm
internal-adminis unreachable from the host:curl -i http://127.0.0.1:18083/ssrf-marker # connection refused / fail docker compose ps # internal-admin has NO host port mapping - Send the request named
POST image-prefetch DNS rebinding triggerfromrequests.http, or with curl:curl -i -X POST http://127.0.0.1:18082/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "ollama-local/gemma3", "messages": [{"role":"user","content":[ {"type":"text","text":"reproduction image-prefetch trigger"}, {"type":"image_url","image_url":{"url":"http://rebind.9r.test:8080/ssrf-marker?case=rebind-trigger"}} ]}], "stream": false }'
Impact
- SSRF to internal HTTP services reachable from the 9router host/container.
- Depending on the environment, this can reach cloud metadata endpoints, internal admin panels, or be used for internal service discovery.
- Blind / semi-blind SSRF when the fetched response is not returned to the attacker; an exfil variant (pointing the image at an internal endpoint that returns valid image bytes) can return internal content base64-encoded to the upstream.
- Requires a code path that prefetches/normalizes remote images for vision-capable providers.
- No real credential is needed for the reproduction.
Suggested Fix
- Pin the resolved IP after validation and connect to that IP (resolve once, then reuse the address for the fetch).
- Block private, loopback, link-local, multicast, and cloud-metadata ranges at connect time, not only at validation time.
- Perform DNS resolution and IP checks immediately before the request and against the address actually used to connect.
- Disable redirects, or re-validate every redirect target with the same checks.
- Enforce an allowlist for image-fetch domains where feasible.
- Add a timeout, a response size limit, and a content-type check.
- Record
GHSA-cmhj-wh2f-9cgx- CVSS 3.1
- 7.4 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:L - Weakness
- CWE-367, CWE-918
- Updated
- 2026-11-02
Affected products
Affected packages
History
| Recorded | Changed | Sources |
|---|---|---|
| aliases, published | EUVD | |
| first indexed | CVE List, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-56676 is a high vulnerability (CVSS 7.4) in Decolua 9router, published July 10, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.19%, the 8th percentile. Fixed in 9router 0.5.2.
References
github.com/decolua/9router/security/advisories/GHSA-cmhj-wh2f-9cgx
github.com/decolua/9router/commit/c7d07448c58bec1200741de0b73305b860416b82
github.com/decolua/9router/releases/tag/v0.5.2
nvd.nist.gov/vuln/detail/CVE-2026-56676
github.com/advisories/GHSA-cmhj-wh2f-9cgx
github.com/CVEProject/cvelistV5/tree/main/cves/2026/56xxx/CVE-2026-56676.json
github.com/decolua/9router