From 49afb3d9d9deedf6dea3a6dd5c50e85e7d8bcb07 Mon Sep 17 00:00:00 2001 From: thelongestusernameofall Date: Fri, 24 Oct 2025 10:12:40 +0800 Subject: [PATCH] Fix(security): block unsafe pickle deserialization to mitigate CVE-2025-10164 (#11909) Co-authored-by: Chengxing Xie Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- docs/index.rst | 6 +++ docs/security/acknowledgements.md | 3 ++ python/sglang/srt/utils/common.py | 73 ++++++++++++++++++++++++++++++- 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 docs/security/acknowledgements.md diff --git a/docs/index.rst b/docs/index.rst index 4eb596394..d9ce09239 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -98,3 +98,9 @@ Its core features include: references/custom_chat_template.md references/frontend/frontend_index.rst references/learn_more.md + +.. toctree:: + :maxdepth: 1 + :caption: Security Acknowledgement + + security/acknowledgements.md diff --git a/docs/security/acknowledgements.md b/docs/security/acknowledgements.md new file mode 100644 index 000000000..9873da9b5 --- /dev/null +++ b/docs/security/acknowledgements.md @@ -0,0 +1,3 @@ +| Time | CVE ID | Credit to | Affected Versions | Severity | Impact | Description | +|------------|--------------|------------------|---------------------------|------------|----------------------|-------------| +| 2025-09-09 | CVE-2025-10164 | Simon Huang, pjf | ≥ 0.4.6 & ≤ 0.5.3 | Critical | Remote Code Execution | A security flaw exists in lmsys sglang versions ≥ 0.4.6 and ≤ 0.5.3. The vulnerability arises from the use of unsafe pickle deserialization of the `serialized_named_tensors` parameter in the `/update_weights_from_tensor` API endpoint, which could allow a remote attacker to execute arbitrary code on the server by sending a specially crafted payload. | diff --git a/python/sglang/srt/utils/common.py b/python/sglang/srt/utils/common.py index daf0c7dcd..a09c5fc98 100644 --- a/python/sglang/srt/utils/common.py +++ b/python/sglang/srt/utils/common.py @@ -2099,7 +2099,78 @@ class MultiprocessingSerializer: # Decode base64 string to bytes data = pybase64.b64decode(data, validate=True) - return ForkingPickler.loads(data) + class SafeUnpickler(pickle.Unpickler): + ALLOWED_MODULE_PREFIXES = { + # --- Python types --- + "builtins.", + "collections.", + "copyreg.", + "functools.", + "itertools.", + "operator.", + "types.", + "weakref.", + # --- PyTorch types --- + "torch.", + "torch._tensor.", + "torch.storage.", + "torch.nn.parameter.", + "torch.autograd.function.", + # --- torch distributed --- + "torch.distributed.", + "torch.distributed._shard.", + "torch.distributed._composable.", + "torch._C._distributed_c10d.", + "torch._C._distributed_fsdp.", + "torch.distributed.optim.", + # --- multiprocessing --- + "multiprocessing.resource_sharer.", + "multiprocessing.reduction.", + "pickletools.", + # --- PEFT / LoRA --- + "peft.", + "transformers.", + "huggingface_hub.", + # --- SGLang & Unitest --- + "sglang.srt.weight_sync.tensor_bucket.", + "sglang.srt.model_executor.model_runner.", + "sglang.srt.layers.", + "sglang.srt.utils.", + } + + DENY_CLASSES = { + ("builtins", "eval"), + ("builtins", "exec"), + ("builtins", "compile"), + ("os", "system"), + ("subprocess", "Popen"), + ("subprocess", "run"), + ("codecs", "decode"), + ("types", "CodeType"), + ("types", "FunctionType"), + } + + def find_class(self, module, name): + # Block deterministic attacks + if (module, name) in self.DENY_CLASSES: + raise RuntimeError( + f"Blocked unsafe class loading ({module}.{name}), " + f"to prevent exploitation of CVE-2025-10164" + ) + # Allowlist of safe-to-load modules. + if any( + (module + ".").startswith(prefix) + for prefix in self.ALLOWED_MODULE_PREFIXES + ): + return super().find_class(module, name) + + # Block everything else. (Potential attack surface) + raise RuntimeError( + f"Blocked unsafe class loading ({module}.{name}), " + f"to prevent exploitation of CVE-2025-10164" + ) + + return SafeUnpickler(io.BytesIO(data)).load() def debug_timing(func):