Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-sglang for openSUSE:Factory 
checked in at 2026-09-23 14:36:11
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-sglang (Old)
 and      /work/SRC/openSUSE:Factory/.python-sglang.new.383539 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-sglang"

Wed Sep 23 14:36:11 2026 rev:4 rq:1379916 version:0.5.20

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-sglang/python-sglang.changes      
2026-09-08 16:56:48.921728988 +0200
+++ /work/SRC/openSUSE:Factory/.python-sglang.new.383539/python-sglang.changes  
2026-09-23 14:37:38.147027789 +0200
@@ -1,0 +2,77 @@
+Tue Sep 22 19:29:07 UTC 2026 - Martin Pluskal <[email protected]>
+
+- CVE-2026-86793: SafeUnpickler gated pickle deserialization on
+  a module-prefix allowlist, and a prefix admits every name
+  below it, leaving builtins.getattr, builtins.__import__ and
+  torch.storage._load_from_bytes reachable from the
+  unauthenticated /update_weights_from_tensor endpoint and from
+  the encoder and weight-cache channels; backport upstream's
+  two-part fix, which replaces the prefixes with an exact
+  (module, name) allowlist and serves _load_from_bytes through
+  torch.load(weights_only=True) with a storage type check
+  (boo#1280091)
+  * sglang-safe-unpickler-stdlib-globals.patch, commit
+    882577451e (PR 39858)
+  * sglang-safe-unpickler-explicit-globals.patch, commit
+    5b42d10edf (PR 40259)
+
+-------------------------------------------------------------------
+Tue Sep 22 18:17:45 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to 0.5.20:
+  * /v1/responses no longer stores results unless the server is
+    started with --enable-response-store; retrieval,
+    previous_response_id chaining and background requests are
+    rejected without it
+  * Prefill context parallelism v1 and its SGLANG_ENABLE_CP_V2
+    gate are gone; the strategy-based path is the only one left
+  * Seventeen deprecated CLI flags are removed,
+    get_global_server_args() now raises, and ServerArgs is no
+    longer a dataclass, so dataclasses.asdict on it stops working
+  * Sampling-mask capacity moves to --sampling-mask-max-tokens
+    (default 4096); the old environment variable is rejected
+  * The unified radix tree keeps the sliding-window state where
+    requests fork from a shared prefix, so branches reuse it
+  * gRPC: GetIsReady is replaced by a WatchEngineState stream
+    carrying health, pause state, instance id and discovery
+  * The Rust multimodal preprocessor's per-request media budget
+    rises from 256 MiB to 1.25 GiB
+  * Most of the rest is CUDA, ROCm and NPU kernel work that this
+    CPU build does not compile
+- Rebase sglang-relax-cpu-requirements.patch for the reshuffled
+  pyproject_cpu.toml; it also drops the newly added torchcodec
+  dependency, which is not in Factory
+- Regenerate vendor.tar.zst
+  * The crate set advances to rustls 0.23.45, which fixes
+    RUSTSEC-2026-0285
+- This build is not affected by three open prefill/decode
+  disaggregation issues: sglang/srt/disaggregation ships intact
+  and 0.5.20 leaves the code paths unchanged from 0.5.19, but
+  all three run in KV manager threads that start only under
+  the prefill or decode --disaggregation-mode (default null),
+  and no manager is ever constructed - each needs a KV transfer
+  backend whose transport library is not packaged, so mooncake
+  raises ImportError as the model runner starts, nixl inside
+  NixlKVManager, mori already at module import and ascend
+  without memfabric_hybrid, while fake has no ZeroMQ rank port
+  and starts no threads
+  * CVE-2026-94570 (boo#1282324): missing input validation for
+    AUX_DATA ZeroMQ control messages in the decode worker, read
+    only by the Mooncake and Mori decode threads
+  * CVE-2026-93838 (boo#1281937): unbounded memory allocation
+    in handle_staging_req, called only from the Mooncake and
+    NIXL decode threads
+  * CVE-2026-93688 (boo#1281936): unvalidated bootstrap_room
+    values in the Mooncake prefill bootstrap thread
+
+-------------------------------------------------------------------
+Tue Sep 22 18:14:10 UTC 2026 - Martin Pluskal <[email protected]>
+
+- CVE-2026-93088: the disaggregated-diffusion orchestrator read
+  pickles off an unauthenticated bound ZeroMQ socket, allowing
+  arbitrary code execution; stop installing
+  sglang/multimodal_gen/runtime/disaggregation (boo#1282323)
+  * Costs nothing: that runtime imports the unpackaged diffusers
+    and cache_dit modules, so it could never start here
+
+-------------------------------------------------------------------

Old:
----
  sglang-0.5.19.tar.gz

New:
----
  sglang-0.5.20.tar.gz
  sglang-safe-unpickler-explicit-globals.patch
  sglang-safe-unpickler-stdlib-globals.patch

----------(New B)----------
  New:    882577451e (PR 39858)
  * sglang-safe-unpickler-explicit-globals.patch, commit
    5b42d10edf (PR 40259)
  New:  (boo#1280091)
  * sglang-safe-unpickler-stdlib-globals.patch, commit
    882577451e (PR 39858)
----------(New E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-sglang.spec ++++++
--- /var/tmp/diff_new_pack.PkglCD/_old  2026-09-23 14:37:45.054316615 +0200
+++ /var/tmp/diff_new_pack.PkglCD/_new  2026-09-23 14:37:45.056316699 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           python-sglang
-Version:        0.5.19
+Version:        0.5.20
 Release:        0
 Summary:        Fast serving framework for large language models
 # Legal-Review-Notice: sgl-model-gateway and CUDA AOT kernels
@@ -48,6 +48,10 @@
 Patch2:         sglang-cpu-rust-exts.patch
 # PATCH-FIX-OPENSUSE sglang-grpc-system-protoc.patch -- use system protoc 
instead of protoc-bin-vendored
 Patch3:         sglang-grpc-system-protoc.patch
+# PATCH-FIX-UPSTREAM sglang-safe-unpickler-stdlib-globals.patch boo#1280091 -- 
CVE-2026-86793: sgl-project/sglang commit 882577451e (PR 39858), replace 
SafeUnpickler's standard-library module prefixes with exact globals
+Patch4:         sglang-safe-unpickler-stdlib-globals.patch
+# PATCH-FIX-UPSTREAM sglang-safe-unpickler-explicit-globals.patch boo#1280091 
-- CVE-2026-86793: sgl-project/sglang commit 5b42d10edf (PR 40259), drop the 
remaining module prefixes and route torch.storage._load_from_bytes through a 
weights_only torch.load
+Patch5:         sglang-safe-unpickler-explicit-globals.patch
 BuildRequires:  %{python_module IPython}
 BuildRequires:  %{python_module Pillow}
 BuildRequires:  %{python_module SoundFile}
@@ -227,13 +231,19 @@
 pushd python
 %pyproject_install
 popd
+# multimodal_gen/runtime/disaggregation pickles requests straight off a bound
+# ZeroMQ socket with no authentication (CVE-2026-93088). The runtime it belongs
+# to needs diffusers and cache_dit, neither of which is packaged, so nothing
+# here can reach it -- drop it rather than ship a live gadget.
 %{python_expand \
 rm -rf %{buildroot}%{$python_sitearch}/sglang/test \
        %{buildroot}%{$python_sitearch}/sglang/kernels/aot \
        %{buildroot}%{$python_sitearch}/sglang/multimodal_gen/test \
+       
%{buildroot}%{$python_sitearch}/sglang/multimodal_gen/runtime/disaggregation \
        %{buildroot}%{$python_sitelib}/sglang/test \
        %{buildroot}%{$python_sitelib}/sglang/kernels/aot \
-       %{buildroot}%{$python_sitelib}/sglang/multimodal_gen/test
+       %{buildroot}%{$python_sitelib}/sglang/multimodal_gen/test \
+       
%{buildroot}%{$python_sitelib}/sglang/multimodal_gen/runtime/disaggregation
 # CPU flavour never JIT-compiles these; shipping them scores
 # devel-file-in-non-devel-package (badness 50 each) and fails rpmlint.
 find %{buildroot} -type f \( \

++++++ sglang-0.5.19.tar.gz -> sglang-0.5.20.tar.gz ++++++
/work/SRC/openSUSE:Factory/python-sglang/sglang-0.5.19.tar.gz 
/work/SRC/openSUSE:Factory/.python-sglang.new.383539/sglang-0.5.20.tar.gz 
differ: char 29, line 1

++++++ sglang-relax-cpu-requirements.patch ++++++
--- /var/tmp/diff_new_pack.PkglCD/_old  2026-09-23 14:37:45.146320462 +0200
+++ /var/tmp/diff_new_pack.PkglCD/_new  2026-09-23 14:37:45.150320630 +0200
@@ -38,7 +38,7 @@
    "orjson",
    "outlines",
    "packaging",
-@@ -45,31 +42,27 @@
+@@ -45,32 +42,27 @@
    "pillow",
    "prometheus-client>=0.20.0",
    "psutil",
@@ -52,7 +52,7 @@
    "scipy",
    "sentencepiece",
    "setproctitle",
--  "smg-grpc-servicer>=0.5.0",
+-  "smg-grpc-servicer>=0.9.0",
 -  "soundfile==0.13.1",
 +  "soundfile>=0.13.1",
    "tabulate",
@@ -60,6 +60,7 @@
 -  "timm==1.0.16",
 -  "torch==2.12.0",
 -  "torchaudio==2.11.0",
+-  "torchcodec==0.12.0 ; sys_platform != 'linux' or (sys_platform == 'linux' 
and platform_machine != 'aarch64' and platform_machine != 'arm64' and 
platform_machine != 'armv7l')",
 -  "torchvision==0.27.0",
 +  "timm>=1.0.16",
 +  "torch>=2.12.0",
@@ -77,7 +78,7 @@
    "zstandard",
  ]
  
-@@ -126,6 +119,12 @@
+@@ -128,6 +120,12 @@
    "kernels/**/*"
  ]
  
@@ -90,7 +91,7 @@
  [tool.setuptools.packages.find]
  exclude = [
    "assets*",
-@@ -134,6 +133,8 @@
+@@ -136,6 +134,8 @@
    "dist*",
    "playground*",
    "scripts*",
@@ -99,7 +100,7 @@
    "tests*",
  ]
  
-@@ -145,6 +146,8 @@
+@@ -147,6 +147,8 @@
    "dist*",
    "playground*",
    "scripts*",

++++++ sglang-safe-unpickler-explicit-globals.patch ++++++
>From 5b42d10edfa4b626b1e37026577eb5706e89b69a Mon Sep 17 00:00:00 2001
From: Yonghao Zhuang <[email protected]>
Date: Fri, 18 Sep 2026 22:38:11 -0700
Subject: [PATCH] fix: restrict SafeUnpickler to explicit globals (#40259)

Co-authored-by: yhzhuang <[email protected]>
Co-authored-by: Jihui Yang <[email protected]>
---
 python/sglang/srt/utils/common.py | 228 +++++++++++++++++++++++++-----
 1 file changed, 196 insertions(+), 32 deletions(-)

diff --git a/python/sglang/srt/utils/common.py 
b/python/sglang/srt/utils/common.py
index 6aed66de2153..5802c11b1bec 100644
--- a/python/sglang/srt/utils/common.py
+++ b/python/sglang/srt/utils/common.py
@@ -2966,6 +2966,15 @@ def normalize_serialized_named_tensor_payloads(
     return [normalize_serialized_named_tensor_payload(data) for data in 
payloads]
 
 
+def _safe_load_torch_storage(data: bytes):
+    storage = torch.load(io.BytesIO(data), weights_only=True)
+    if not isinstance(storage, (torch.storage.TypedStorage, 
torch.UntypedStorage)):
+        raise pickle.UnpicklingError(
+            f"Expected a Torch storage, got {type(storage).__name__}"
+        )
+    return storage
+
+
 class SafeUnpickler(pickle.Unpickler):
     # Standard-library modules expose powerful callables alongside harmless 
data
     # types. Keep these globals exact so a newly added callable is denied by
@@ -2989,6 +2998,9 @@ class SafeUnpickler(pickle.Unpickler):
         ("collections", "OrderedDict"),
         ("collections", "defaultdict"),
         ("collections", "deque"),
+        ("collections", "Counter"),
+        ("copyreg", "__newobj__"),
+        ("copyreg", "__newobj_ex__"),
         ("functools", "partial"),
         ("itertools", "chain"),
         ("itertools", "repeat"),
@@ -2996,41 +3008,193 @@ class SafeUnpickler(pickle.Unpickler):
         ("multiprocessing.reduction", "_rebuild_socket"),
         ("multiprocessing.resource_sharer", "DupFd"),
         ("types", "SimpleNamespace"),
-    }
-
-    ALLOWED_MODULE_PREFIXES = {
-        # --- 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.",
-        # --- PEFT / LoRA ---
-        "peft.",
-        "transformers.",
-        "huggingface_hub.",
-        # --- SGLang & Unitest ---
-        "sglang.srt.weight_sync.tensor_bucket.",
-        "sglang.srt.model_executor.model_runner.",
-        "sglang.srt.model_executor.model_runner_components.weight_updater.",
-        "sglang.srt.layers.",
-        "sglang.srt.utils.",
-        "sglang.srt.disaggregation.",
-        "sglang.srt.managers.",
-        "torch_npu.",
+        ("_codecs", "encode"),
+        # --- PyTorch data containers & rebuild functions ---
+        # Code-module prefixes (torch.*, sglang.srt.*) are NOT allowed: they
+        # contain gadgets like sglang.srt.utils.common.dynamic_import
+        ("torch", "Tensor"),
+        ("torch", "BFloat16Tensor"),
+        ("torch", "BoolTensor"),
+        ("torch", "ByteTensor"),
+        ("torch", "CharTensor"),
+        ("torch", "DoubleTensor"),
+        ("torch", "FloatTensor"),
+        ("torch", "HalfTensor"),
+        ("torch", "IntTensor"),
+        ("torch", "LongTensor"),
+        ("torch", "ShortTensor"),
+        ("torch.cuda", "BFloat16Tensor"),
+        ("torch.cuda", "BoolTensor"),
+        ("torch.cuda", "ByteTensor"),
+        ("torch.cuda", "CharTensor"),
+        ("torch.cuda", "DoubleTensor"),
+        ("torch.cuda", "FloatTensor"),
+        ("torch.cuda", "HalfTensor"),
+        ("torch.cuda", "IntTensor"),
+        ("torch.cuda", "LongTensor"),
+        ("torch.cuda", "ShortTensor"),
+        ("torch.cuda.sparse", "BFloat16Tensor"),
+        ("torch.cuda.sparse", "ByteTensor"),
+        ("torch.cuda.sparse", "CharTensor"),
+        ("torch.cuda.sparse", "DoubleTensor"),
+        ("torch.cuda.sparse", "FloatTensor"),
+        ("torch.cuda.sparse", "HalfTensor"),
+        ("torch.cuda.sparse", "IntTensor"),
+        ("torch.cuda.sparse", "LongTensor"),
+        ("torch.cuda.sparse", "ShortTensor"),
+        ("torch.sparse", "BFloat16Tensor"),
+        ("torch.sparse", "ByteTensor"),
+        ("torch.sparse", "CharTensor"),
+        ("torch.sparse", "DoubleTensor"),
+        ("torch.sparse", "FloatTensor"),
+        ("torch.sparse", "HalfTensor"),
+        ("torch.sparse", "IntTensor"),
+        ("torch.sparse", "LongTensor"),
+        ("torch.sparse", "ShortTensor"),
+        ("torch", "Size"),
+        ("torch", "device"),
+        ("torch", "dtype"),
+        ("torch", "bfloat16"),
+        ("torch", "bit"),
+        ("torch", "bits16"),
+        ("torch", "bits1x8"),
+        ("torch", "bits2x4"),
+        ("torch", "bits4x2"),
+        ("torch", "bits8"),
+        ("torch", "bool"),
+        ("torch", "cdouble"),
+        ("torch", "cfloat"),
+        ("torch", "chalf"),
+        ("torch", "complex128"),
+        ("torch", "complex32"),
+        ("torch", "complex64"),
+        ("torch", "double"),
+        ("torch", "float"),
+        ("torch", "float16"),
+        ("torch", "float32"),
+        ("torch", "float4_e2m1fn_x2"),
+        ("torch", "float64"),
+        ("torch", "float8_e4m3fn"),
+        ("torch", "float8_e4m3fnuz"),
+        ("torch", "float8_e5m2"),
+        ("torch", "float8_e5m2fnuz"),
+        ("torch", "float8_e8m0fnu"),
+        ("torch", "half"),
+        ("torch", "int"),
+        ("torch", "int1"),
+        ("torch", "int16"),
+        ("torch", "int2"),
+        ("torch", "int3"),
+        ("torch", "int32"),
+        ("torch", "int4"),
+        ("torch", "int5"),
+        ("torch", "int6"),
+        ("torch", "int64"),
+        ("torch", "int7"),
+        ("torch", "int8"),
+        ("torch", "long"),
+        ("torch", "qint32"),
+        ("torch", "qint8"),
+        ("torch", "quint2x4"),
+        ("torch", "quint4x2"),
+        ("torch", "quint8"),
+        ("torch", "short"),
+        ("torch", "uint1"),
+        ("torch", "uint16"),
+        ("torch", "uint2"),
+        ("torch", "uint3"),
+        ("torch", "uint32"),
+        ("torch", "uint4"),
+        ("torch", "uint5"),
+        ("torch", "uint6"),
+        ("torch", "uint64"),
+        ("torch", "uint7"),
+        ("torch", "uint8"),
+        ("torch.nn.parameter", "Parameter"),
+        ("torch.serialization", "_get_layout"),
+        ("torch._utils", "_rebuild_tensor"),
+        ("torch._utils", "_rebuild_tensor_v2"),
+        ("torch._utils", "_rebuild_tensor_v3"),
+        ("torch._utils", "_rebuild_parameter"),
+        ("torch._utils", "_rebuild_parameter_with_state"),
+        ("torch._utils", "_rebuild_qtensor"),
+        ("torch._utils", "_rebuild_sparse_tensor"),
+        ("torch._utils", "_rebuild_meta_tensor_no_storage"),
+        ("torch._utils", "_rebuild_wrapper_subclass"),
+        ("torch._utils", "_rebuild_device_tensor_from_numpy"),
+        ("torch._utils", "_rebuild_device_tensor_from_cpu_tensor"),
+        ("torch._tensor", "_rebuild_from_type_v2"),
+        ("torch.storage", "UntypedStorage"),
+        ("torch.storage", "_UntypedStorage"),
+        ("torch.storage", "TypedStorage"),
+        ("torch", "UntypedStorage"),
+        ("torch", "BFloat16Storage"),
+        ("torch", "BoolStorage"),
+        ("torch", "ByteStorage"),
+        ("torch", "CharStorage"),
+        ("torch", "ComplexDoubleStorage"),
+        ("torch", "ComplexFloatStorage"),
+        ("torch", "DoubleStorage"),
+        ("torch", "FloatStorage"),
+        ("torch", "HalfStorage"),
+        ("torch", "IntStorage"),
+        ("torch", "LongStorage"),
+        ("torch", "QInt32Storage"),
+        ("torch", "QInt8Storage"),
+        ("torch", "QUInt2x4Storage"),
+        ("torch", "QUInt4x2Storage"),
+        ("torch", "QUInt8Storage"),
+        ("torch", "ShortStorage"),
+        ("torch.cuda", "BFloat16Storage"),
+        ("torch.cuda", "BoolStorage"),
+        ("torch.cuda", "ByteStorage"),
+        ("torch.cuda", "CharStorage"),
+        ("torch.cuda", "ComplexDoubleStorage"),
+        ("torch.cuda", "ComplexFloatStorage"),
+        ("torch.cuda", "DoubleStorage"),
+        ("torch.cuda", "FloatStorage"),
+        ("torch.cuda", "HalfStorage"),
+        ("torch.cuda", "IntStorage"),
+        ("torch.cuda", "LongStorage"),
+        ("torch.cuda", "ShortStorage"),
+        ("torch.multiprocessing.reductions", "rebuild_tensor"),
+        ("torch.multiprocessing.reductions", "rebuild_meta_tensor"),
+        ("torch.multiprocessing.reductions", "rebuild_cuda_tensor"),
+        ("sglang.srt.utils.patch_torch", "_rebuild_cuda_tensor_modified"),
+        ("torch_npu.multiprocessing.reductions", "rebuild_npu_tensor"),
+        ("sglang.srt.utils.patch_torch", "_rebuild_npu_tensor_modified"),
+        ("torch.multiprocessing.reductions", "rebuild_nested_tensor"),
+        ("torch.multiprocessing.reductions", "rebuild_sparse_coo_tensor"),
+        ("torch.multiprocessing.reductions", 
"rebuild_sparse_compressed_tensor"),
+        ("torch.multiprocessing.reductions", "rebuild_storage_fd"),
+        ("torch.multiprocessing.reductions", "rebuild_storage_filename"),
+        ("torch.multiprocessing.reductions", "rebuild_storage_empty"),
+        ("torch.multiprocessing.reductions", "rebuild_typed_storage"),
+        ("torch.multiprocessing.reductions", "rebuild_typed_storage_child"),
+        ("torch", "per_tensor_affine"),
+        ("torch", "per_tensor_symmetric"),
+        ("torch", "per_channel_affine"),
+        ("torch", "per_channel_symmetric"),
+        ("torch", "per_channel_affine_float_qparams"),
+        # --- SGLang data containers only (no code modules) ---
+        ("sglang.srt.managers.io_struct", "GenerateReqInput"),
+        ("sglang.srt.managers.io_struct", "EmbeddingReqInput"),
+        ("sglang.srt.disaggregation.encoder.receiver", "EmbeddingData"),
+        ("sglang.srt.managers.schedule_batch", "Modality"),
+        ("sglang.srt.weight_sync.tensor_bucket", "FlattenedTensorMetadata"),
+        ("sglang.srt.weight_sync.tensor_bucket", "FlattenedTensorBucket"),
+        (
+            "sglang.srt.model_executor.model_runner_components.weight_updater",
+            "LocalSerializedTensor",
+        ),
+        ("sglang.srt.model_executor.model_runner", "LocalSerializedTensor"),
     }
 
     def find_class(self, module, name):
-        if (module, name) in self.ALLOWED_GLOBALS or any(
-            (module + ".").startswith(prefix) for prefix in 
self.ALLOWED_MODULE_PREFIXES
-        ):
+        if (module, name) == ("torch.storage", "_load_from_bytes"):
+            # Torch's helper calls an unrestricted nested torch.load.
+            return _safe_load_torch_storage
+        if (module, name) in self.ALLOWED_GLOBALS:
             return super().find_class(module, name)
 
         raise RuntimeError(

++++++ sglang-safe-unpickler-stdlib-globals.patch ++++++
>From 882577451e764a515df2a386a055012e8f075a16 Mon Sep 17 00:00:00 2001
From: Lianmin Zheng <[email protected]>
Date: Thu, 17 Sep 2026 01:09:55 -0700
Subject: [PATCH] Restrict SafeUnpickler standard-library globals (#39858)

Co-authored-by: jiayisuse <[email protected]>
---
 python/sglang/srt/utils/common.py             | 69 +++++++++---------
 .../unit/utils/test_safe_unpickler.py         | 72 +++++++++++++++++++
 2 files changed, 105 insertions(+), 36 deletions(-)
 create mode 100644 test/registered/unit/utils/test_safe_unpickler.py

diff --git a/python/sglang/srt/utils/common.py 
b/python/sglang/srt/utils/common.py
index 5509adfdeca0..6aed66de2153 100644
--- a/python/sglang/srt/utils/common.py
+++ b/python/sglang/srt/utils/common.py
@@ -2967,16 +2967,38 @@ def normalize_serialized_named_tensor_payloads(
 
 
 class SafeUnpickler(pickle.Unpickler):
-    ALLOWED_MODULE_PREFIXES = {
+    # Standard-library modules expose powerful callables alongside harmless 
data
+    # types. Keep these globals exact so a newly added callable is denied by
+    # default instead of silently expanding the unpickling attack surface.
+    ALLOWED_GLOBALS = {
         # --- Python types ---
-        "builtins.",
-        "collections.",
-        "copyreg.",
-        "functools.",
-        "itertools.",
-        "operator.",
-        "types.",
-        "weakref.",
+        ("builtins", "bool"),
+        ("builtins", "bytearray"),
+        ("builtins", "bytes"),
+        ("builtins", "complex"),
+        ("builtins", "dict"),
+        ("builtins", "float"),
+        ("builtins", "frozenset"),
+        ("builtins", "int"),
+        ("builtins", "list"),
+        ("builtins", "range"),
+        ("builtins", "set"),
+        ("builtins", "slice"),
+        ("builtins", "str"),
+        ("builtins", "tuple"),
+        ("collections", "OrderedDict"),
+        ("collections", "defaultdict"),
+        ("collections", "deque"),
+        ("functools", "partial"),
+        ("itertools", "chain"),
+        ("itertools", "repeat"),
+        ("multiprocessing.reduction", "_rebuild_partial"),
+        ("multiprocessing.reduction", "_rebuild_socket"),
+        ("multiprocessing.resource_sharer", "DupFd"),
+        ("types", "SimpleNamespace"),
+    }
+
+    ALLOWED_MODULE_PREFIXES = {
         # --- PyTorch types ---
         "torch.",
         "torch._tensor.",
@@ -2990,10 +3012,6 @@ class SafeUnpickler(pickle.Unpickler):
         "torch._C._distributed_c10d.",
         "torch._C._distributed_fsdp.",
         "torch.distributed.optim.",
-        # --- multiprocessing ---
-        "multiprocessing.resource_sharer.",
-        "multiprocessing.reduction.",
-        "pickletools.",
         # --- PEFT / LoRA ---
         "peft.",
         "transformers.",
@@ -3009,35 +3027,14 @@ class SafeUnpickler(pickle.Unpickler):
         "torch_npu.",
     }
 
-    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(
+        if (module, name) in self.ALLOWED_GLOBALS or 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"
+            f"Blocked unsafe global ({module}.{name}) during pickle 
deserialization"
         )
 
 
diff --git a/test/registered/unit/utils/test_safe_unpickler.py 
b/test/registered/unit/utils/test_safe_unpickler.py
new file mode 100644
index 000000000000..441c5c8b7a67
--- /dev/null
+++ b/test/registered/unit/utils/test_safe_unpickler.py
@@ -0,0 +1,72 @@
+import pickle
+import unittest
+from collections import OrderedDict, defaultdict, deque
+from functools import partial
+from types import SimpleNamespace
+
+import torch
+
+from sglang.srt.utils.common import MultiprocessingSerializer, 
safe_pickle_loads
+from sglang.test.ci.ci_register import register_cpu_ci
+from sglang.test.test_utils import CustomTestCase
+
+register_cpu_ci(est_time=2, suite="base-a-test-cpu")
+
+
+class TestSafeUnpickler(CustomTestCase):
+    def test_rejects_dangerous_builtin_globals(self):
+        for name in ("__import__", "getattr", "eval", "exec", "compile", 
"open"):
+            with (
+                self.subTest(name=name),
+                self.assertRaisesRegex(
+                    RuntimeError, rf"Blocked unsafe global 
\(builtins\.{name}\)"
+                ),
+            ):
+                # GLOBAL resolves the callable but does not invoke it. This 
exercises
+                # the deserialization boundary without constructing an exploit 
chain.
+                safe_pickle_loads(f"cbuiltins\n{name}\n.".encode())
+
+    def test_rejects_unlisted_standard_library_globals(self):
+        for module, name in (
+            ("copyreg", "_reconstructor"),
+            ("operator", "attrgetter"),
+            ("types", "FunctionType"),
+        ):
+            with (
+                self.subTest(module=module, name=name),
+                self.assertRaisesRegex(
+                    RuntimeError, rf"Blocked unsafe global 
\({module}\.{name}\)"
+                ),
+            ):
+                safe_pickle_loads(f"c{module}\n{name}\n.".encode())
+
+    def test_round_trips_safe_standard_library_types(self):
+        value = SimpleNamespace(
+            values=OrderedDict([("items", deque([1, 2]))]),
+            factory=defaultdict(list, {"items": [3]}),
+            index=slice(1, 4),
+            parser=partial(int, base=10),
+        )
+
+        restored = safe_pickle_loads(
+            pickle.dumps(value, protocol=pickle.HIGHEST_PROTOCOL)
+        )
+
+        self.assertEqual(restored.values, value.values)
+        self.assertEqual(restored.factory, value.factory)
+        self.assertEqual(restored.index, value.index)
+        self.assertEqual(restored.parser("11"), 11)
+
+    def test_round_trips_tensor_payload(self):
+        value = [("weight", torch.arange(6).reshape(2, 3))]
+
+        restored = MultiprocessingSerializer.deserialize(
+            MultiprocessingSerializer.serialize(value)
+        )
+
+        self.assertEqual(restored[0][0], "weight")
+        self.assertTrue(torch.equal(restored[0][1], value[0][1]))
+
+
+if __name__ == "__main__":
+    unittest.main()

++++++ vendor.tar.zst ++++++
/work/SRC/openSUSE:Factory/python-sglang/vendor.tar.zst 
/work/SRC/openSUSE:Factory/.python-sglang.new.383539/vendor.tar.zst differ: 
char 7, line 1

Reply via email to