GHSA-7prp-2623-8g45: Pip/djust vulnerability
Impact The djust live transport resolves the LiveView to mount from a client-supplied dotted path by calling import(modulepath, ...). 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 LIVEVIEWALLOWEDMODULES allowlist that should contain this is fail-open (if allowedmodules: — 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 / liveredirectmount / urlchange 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 handlemount (import of the client view) - python/djust/runtime.py ViewRuntime.dispatchmount / instantiateview (SSE + urlchange 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.viewresolution.isviewimportallowed): 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 LIVEVIEWALLOWEDMODULES 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 instantiateview).
Workarounds Set LIVEVIEWALLOWEDMODULES 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.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/djustto a version that resolves this vulnerability.Fixed in 1.0.7 - Configuration
Set LIVEVIEW_ALLOWED_MODULES (module allowlist) to the narrowest set of modules that contain your mountable LiveView classes. Ensure it is configured (do not leave it unset), because the allowlist is fail-open when allowed_modules is unset and uses loose startswith matching.
djust live transport / view resolution gate LIVEVIEW_ALLOWED_MODULES = Set to the narrow list of modules that contain your mountable LiveView classes. - Compensating control
If LIVEVIEW_ALLOWED_MODULES cannot be immediately set, restrict network access to the unauthenticated WebSocket endpoint that accepts mount/live_redirect_mount/url_change frames (and/or the SSE mount endpoint) so only trusted clients can reach the import sinks.
Event History
Frequently Asked Questions
Are deployments using the default configuration affected?
Yes. When LIVEVIEW_ALLOWED_MODULES is unset, the allowlist check is skipped, so the default configuration is fail-open.
What access does an attacker need?
An attacker only needs to reach the application's WebSocket or SSE live transport. The WebSocket handshake does not require authentication, and per-view authentication occurs only after the module has been imported and instantiated.
Does configuring LIVEVIEW_ALLOWED_MODULES fully prevent exploitation?
Not necessarily. The allowlist uses loose startswith matching, so its protection depends on the configured module prefixes and does not provide exact module-name matching.
How can I identify an exposed deployment?
A deployment is exposed if its live transport accepts mount, live_redirect_mount, url_change, or SSE mount requests and LIVEVIEW_ALLOWED_MODULES is unset. Even when the setting is configured, review it because matching is prefix-based rather than exact.