PT-2026-105795 · Pypi · Djust

Publicado

2026-10-01

·

Atualizado

2026-10-01

CVSS v4.0

8.8

Alta

VetorAV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:H/VA:L/SC:N/SI:N/SA:N

Impact

The djust live transport resolves the LiveView to mount from a client-supplied dotted path by calling import (module path, ...). The module is imported — running its top-level code (import side effects) — before the framework checks that the resolved object is a LiveView subclass and before any per-view authentication. The LIVEVIEW ALLOWED MODULES allowlist that should contain this is fail-open (if allowed modules: — skipped when the setting is unset, the framework default) and uses loose startswith matching.
An unauthenticated WebSocket client (the WS handshake does not require auth; per-view auth runs only after import + instantiate) can therefore send a mount / live redirect mount / url change frame (or an SSE mount) with view = "<any.importable.module>.AnyName" and cause the server to import — and execute the top-level code of — any importable Python module by name.
Consequences: server-side execution of arbitrary importable modules' import-time side effects by an unauthenticated client (effectively RCE-by-proxy on any host that has a side-effectful importable module), denial of service (import bombs / expensive dependency trees), and a module/class enumeration oracle via distinct error strings.
Reproduced end-to-end: an unauthenticated WebsocketCommunicator mount frame with the allowlist unset imported and executed a sentinel non-LiveView module before the "not a LiveView subclass" rejection.

Affected code

  • python/djust/websocket.py handle mount (import of the client view)
  • python/djust/runtime.py ViewRuntime.dispatch mount / instantiate view (SSE + url change path)
  • python/djust/sse.py SSE mount
Threat-model entry T4 (docs/audits/websocket-auth-2026-06.md) previously noted the default-open allowlist but understated the impact as mere LiveView-class probing; the real primitive is arbitrary-module import + top-level code execution, independent of whether the target is a LiveView.

Patches

Fixed by a fail-closed resolution gate (djust. view resolution.is view import allowed): a client view path resolves only if (a) its module is already loaded (sys.modules — so resolving runs no new code; URL-routed views loaded by URLconf at startup keep working with zero config) or (b) it matches LIVEVIEW ALLOWED MODULES on a module-segment boundary (explicit opt-in for lazily-imported views). The gate runs before import at all three sinks (+ defense-in-depth inside instantiate view).

Workarounds

Set LIVEVIEW ALLOWED MODULES to the narrow list of modules that contain your mountable LiveView classes. (Note: pre-patch the allowlist is startswith-matched and the import still precedes the subclass check, so this is mitigation, not a complete fix.)

References

Reproducer + finding writeup retained privately by the maintainer.

Correção

Encontrou algum problema na descrição? Tem algo a acrescentar? Fique à vontade para nos escrever 👾

Identificadores relacionados

PYSEC-2026-4038

Produtos afetados

Djust