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-10-12 22:08:03 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-sglang (Old) and /work/SRC/openSUSE:Factory/.python-sglang.new.3698736 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-sglang" Mon Oct 12 22:08:03 2026 rev:7 rq:1384305 version:0.5.21 Changes: -------- --- /work/SRC/openSUSE:Factory/python-sglang/python-sglang.changes 2026-10-02 23:06:29.378191997 +0200 +++ /work/SRC/openSUSE:Factory/.python-sglang.new.3698736/python-sglang.changes 2026-10-12 22:08:16.548945099 +0200 @@ -1,0 +2,11 @@ +Mon Oct 12 12:12:14 UTC 2026 - Martin Pluskal <[email protected]> + +- CVE-2026-105245: /server_info, gRPC GetServerInfo and + Engine.get_server_info leaked api_key, admin_api_key and + ssl_keyfile_password via full ServerArgs serialization (boo#1284214) + * sglang-30343-server-info-redact.patch +- ZMQ msgpack IPC pickle survey (boo#1284755): top-level PickleWrapper + stays load-bearing for encoder, DP-controller and dumper traffic, + so no decode-side reject is shipped; sockets stay loopback-only + +------------------------------------------------------------------- New: ---- sglang-30343-server-info-redact.patch ----------(New B)---------- New: ssl_keyfile_password via full ServerArgs serialization (boo#1284214) * sglang-30343-server-info-redact.patch - ZMQ msgpack IPC pickle survey (boo#1284755): top-level PickleWrapper ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-sglang.spec ++++++ --- /var/tmp/diff_new_pack.KJ8G3b/_old 2026-10-12 22:08:17.709993532 +0200 +++ /var/tmp/diff_new_pack.KJ8G3b/_new 2026-10-12 22:08:17.711993616 +0200 @@ -50,6 +50,8 @@ Patch3: sglang-grpc-system-protoc.patch # PATCH-FIX-UPSTREAM sglang-40185-bootstrap-room-dedup.patch boo#1283270 -- CVE-2026-102634: sgl-project/sglang PR 40185 (unmerged, head commit 1901ddecfe), report an unknown bootstrap_room as KVPoll.Failed instead of letting check_status raise KeyError, and count KVPoll.Success as bootstrap-done; 2 of the PR's 27 files, the rest being a typing modernisation that does not apply to 0.5.21 Patch4: sglang-40185-bootstrap-room-dedup.patch +# PATCH-FIX-UPSTREAM sglang-30343-server-info-redact.patch boo#1284214 -- CVE-2026-105245: sgl-project/sglang PR 30343 (unmerged as of 2026-10-12, head commit 38787264b70c), mask api_key/admin_api_key/ssl_keyfile_password in /server_info, gRPC GetServerInfo and Engine.get_server_info; rebased onto 0.5.21 resolved_dict() +Patch5: sglang-30343-server-info-redact.patch BuildRequires: %{python_module IPython} BuildRequires: %{python_module Pillow} BuildRequires: %{python_module SoundFile >= 0.13.1} @@ -271,6 +273,8 @@ # graph, the CLI, and that the Rust PyO3 extensions loaded. %python_expand PYTHONPATH=%{buildroot}%{$python_sitearch}:%{buildroot}%{$python_sitelib} $python -B -c "import sglang; print(sglang.__version__); import sglang.srt.rust_extensions._multimodal; import sglang.srt.rust_extensions._grpc" %python_expand PYTHONPATH=%{buildroot}%{$python_sitearch}:%{buildroot}%{$python_sitelib} %{buildroot}%{_bindir}/sglang-%{$python_bin_suffix} --help +# CVE-2026-105245: redacted_asdict() masks set secrets, keeps None, no mutate. +%python_expand PYTHONPATH=%{buildroot}%{$python_sitearch}:%{buildroot}%{$python_sitelib} $python -B -c "from sglang.srt.server_args import ServerArgs; a=ServerArgs(model_path='dummy', api_key='u', admin_api_key='a', ssl_keyfile_password='s'); d=a.redacted_asdict(); assert d['api_key']=='****' and d['admin_api_key']=='****' and d['ssl_keyfile_password']=='****', d; assert a.api_key=='u'; b=ServerArgs(model_path='dummy'); e=b.redacted_asdict(); assert e['api_key'] is None and e['admin_api_key'] is None and e['ssl_keyfile_password'] is None, e" %pre %python_libalternatives_reset_alternative sglang ++++++ sglang-30343-server-info-redact.patch ++++++ Redact api_key/admin_api_key/ssl_keyfile_password from server info endpoints Fixes CVE-2026-105245 (boo#1284214): /server_info (and the deprecated /get_server_info alias), the gRPC bridge get_server_info, and Engine.get_server_info() serialized the full ServerArgs via resolved_dict(), exposing api_key, admin_api_key and ssl_keyfile_password verbatim. With only --admin-api-key set, /server_info is reachable anonymously (AuthLevel.NORMAL), so the admin key leaked to unauthenticated callers; with both keys set, a holder of either key could read the other. Carried from sgl-project/sglang PR 30343 by Rejudge-F (unmerged as of 2026-10-12; closed by github-actions as stale, head commit 38787264b70c5d931abf95ddf29d494fe5a943a8). Rebased onto 0.5.21: upstream wrote ServerArgs.redacted_asdict() around dataclasses.asdict(), but 0.5.21 serializes via ServerArgs.resolved_dict() (msgspec defstruct + resolution pipeline), so redacted_asdict() here masks resolved_dict() instead. The three call sites and SENSITIVE_FIELDS are otherwise the same; the unit test from that PR is not carried (no pytest in %check). --- python/sglang/srt/entrypoints/engine.py | 2 +- python/sglang/srt/entrypoints/grpc_bridge.py | 2 +- python/sglang/srt/entrypoints/http_server.py | 2 +- python/sglang/srt/server_args.py | 17 ++++++++++++++++- 4 files changed, 20 insertions(+), 4 deletions(-) --- a/python/sglang/srt/server_args.py +++ b/python/sglang/srt/server_args.py @@ -265,6 +265,23 @@ for field in record_fields(type(self)) } + # Fields whose values are secrets and must never leave the process via + # introspection surfaces (/server_info, gRPC GetServerInfo, etc.). + SENSITIVE_FIELDS = ("api_key", "admin_api_key", "ssl_keyfile_password") + + def redacted_asdict(self) -> dict[str, Any]: + """Like resolved_dict() but with secret fields masked. + + Keys stay present (so consumers can still detect whether e.g. an + API key is configured), but any set value is replaced with + "****". Unset (None) values are left as None. + """ + d = self.resolved_dict() + for key in self.SENSITIVE_FIELDS: + if d.get(key) is not None: + d[key] = "****" + return d + LANGUAGE_MODEL_ONLY_ARCHITECTURES = ( "MuseGlimmerForConditionalGeneration", "Cosmos3ForConditionalGeneration", --- a/python/sglang/srt/entrypoints/http_server.py +++ b/python/sglang/srt/entrypoints/http_server.py @@ -859,7 +859,7 @@ return msgspec_to_builtins( { - **server_args.resolved_dict(), + **server_args.redacted_asdict(), "launch_command": server_args.launch_command, **_global_state.scheduler_info, "startup_time": _global_state.tokenizer_manager.startup_time, --- a/python/sglang/srt/entrypoints/grpc_bridge.py +++ b/python/sglang/srt/entrypoints/grpc_bridge.py @@ -430,7 +430,7 @@ return json.dumps(result, default=str) def get_server_info(self) -> str: - result: Dict[str, Any] = self.tokenizer_manager.server_args.resolved_dict() + result: Dict[str, Any] = self.tokenizer_manager.server_args.redacted_asdict() # `resolved_dict` answers with what resolution decided; the launch # command answers with what was asked for, and the two are not # derivable from each other. The HTTP and in-process readbacks both --- a/python/sglang/srt/entrypoints/engine.py +++ b/python/sglang/srt/entrypoints/engine.py @@ -1488,7 +1488,7 @@ ) return msgspec_to_builtins( { - **self.tokenizer_manager.server_args.resolved_dict(), + **self.tokenizer_manager.server_args.redacted_asdict(), "launch_command": self.tokenizer_manager.server_args.launch_command, **self._scheduler_init_result.scheduler_infos[0], "startup_time": self.tokenizer_manager.startup_time,
