fix: dispatch_to_all_sids security issue

- move _ws_contexts snapshot inside _contexts_lock critical section, add ctx is None skip logic to prevent security check bypass during concurrent disconnects

keyboardstaff committed Mar 27, 2026 at 23:04 UTC 4065385630bcc918b492725864fe6d463d473bbe
1 file changed +14 -11
helpers/ws.py
+14 -11
@@ -299,24 +299,27 @@ class WsHandler:
299 sid: dict(handlers)
300 for sid, handlers in _active_handlers.items()
301 }
302 + contexts_snapshot = dict(_ws_contexts)
303
304 mgr = self._manager
305 aggregated: list[dict[str, Any]] = []
306 for sid, handlers in snapshot.items():
306 - ctx = _ws_contexts.get(sid)
307 + ctx = contexts_snapshot.get(sid)
308 + # Skip sids whose security context was removed (concurrent disconnect).
309 + if ctx is None:
310 + continue
311 security_errors: list[dict[str, Any]] = []
312 passing: list[WsHandler] = []
313 for _path, instance in handlers.items():
310 - if ctx is not None:
311 - error = _check_security(type(instance), ctx)
312 - if error is not None:
313 - security_errors.append({
314 - "handlerId": instance.identifier,
315 - "ok": False,
316 - "correlationId": cid,
317 - "error": error,
318 - })
319 - continue
314 + error = _check_security(type(instance), ctx)
315 + if error is not None:
316 + security_errors.append({
317 + "handlerId": instance.identifier,
318 + "ok": False,
319 + "correlationId": cid,
320 + "error": error,
321 + })
322 + continue
323 passing.append(instance)
324
325 if mgr is not None and passing: