CVE-2026-61599 Overview
CVE-2026-61599 affects djust, a Django extension that provides Phoenix LiveView-style reactive server-side rendering with Rust-powered performance. Versions prior to 1.0.7 resolve the LiveView class to mount from a client-supplied dotted path by calling __import__(module_path, ...) before verifying that the target is a LiveView subclass and before per-view authentication runs. An unauthenticated WebSocket or SSE client can force the server to import any importable Python module by name, executing its top-level code as an unintended side effect. This vulnerability is classified under CWE-470: Use of Externally-Controlled Input to Select Classes or Code.
Critical Impact
Unauthenticated attackers can trigger arbitrary Python module imports on the server, executing top-level module code without any authentication.
Affected Products
- djust framework versions prior to 1.0.7
- Django applications using djust LiveView transport (WebSocket or SSE)
- Deployments where LIVEVIEW_ALLOWED_MODULES is unset (framework default)
Discovery Timeline
- 2026-09-16 - CVE-2026-61599 published to NVD
- 2026-09-16 - Last updated in NVD database
Technical Details for CVE-2026-61599
Vulnerability Analysis
The djust live transport accepts a client-supplied dotted module path in mount, live_redirect_mount, and url_change frames, as well as SSE mount requests. The framework resolves the target by calling __import__(module_path, ...) directly, which loads the module and executes its top-level code. Only after the import succeeds does djust verify that the resolved object is a LiveView subclass or invoke per-view authentication.
The WebSocket handshake itself does not require authentication, so the entire attack path is reachable without credentials. Any module present on the Python path becomes an import target, and any side effects in that module (connections opened, files touched, subprocesses spawned) execute in the server context.
Root Cause
The LIVEVIEW_ALLOWED_MODULES allowlist that should constrain resolvable modules is fail-open. The guarding logic uses if allowed_modules:, which is skipped entirely when the setting is unset. When the allowlist is configured, it uses loose startswith matching without segment boundaries, allowing bypass with lookalike prefixes. Import precedes both the subclass check and authentication.
Attack Vector
An unauthenticated attacker opens a WebSocket connection to the djust live endpoint and sends a mount frame with view = "<any.importable.module>.AnyName". The server calls __import__ on the supplied path, executing the module's top-level code. The same primitive is reachable through live_redirect_mount and url_change frames, and via SSE mount requests. Impact depends on which modules exist in the Python environment and what side effects their import triggers. See the GitHub Security Advisory GHSA-7prp-2623-8g45 for the full technical breakdown.
Detection Methods for CVE-2026-61599
Indicators of Compromise
- WebSocket mount, live_redirect_mount, or url_change frames containing unexpected dotted module paths in the view field
- SSE mount requests referencing modules outside the application's LiveView package
- Unexpected module import events in Python application logs from anonymous WebSocket sessions
- Outbound network connections or subprocess activity originating from modules not part of normal request flow
Detection Strategies
- Log and inspect the view parameter on all djust transport frames, alerting on values outside a known-good allowlist
- Instrument sys.modules at process start and diff against runtime state to identify unexpected module loads
- Correlate anonymous WebSocket handshakes with import events or new outbound connections within the same process
Monitoring Recommendations
- Enable verbose request logging on the djust WebSocket and SSE endpoints
- Monitor for repeated failed mount attempts with varying view paths, which indicate enumeration
- Track process-level telemetry (file, network, subprocess) tied to the Django worker for anomalous activity following WebSocket traffic
How to Mitigate CVE-2026-61599
Immediate Actions Required
- Upgrade djust to version 1.0.7 or later, which introduces the fail-closed djust._view_resolution.is_view_import_allowed gate
- Audit all Python packages installed in the application environment for modules with dangerous top-level side effects
- Restrict network access to the djust WebSocket and SSE endpoints where feasible until the patch is applied
Patch Information
Version 1.0.7 resolves the issue with a fail-closed resolution gate. A client-supplied view path resolves only if the module is already loaded in sys.modules (so URL-routed views loaded by URLconf at startup continue to work with zero configuration) or if it matches LIVEVIEW_ALLOWED_MODULES on a module-segment boundary. The gate runs before __import__ at all three sinks, with defense-in-depth checks inside _instantiate_view. See djust release v1.0.7 for the fixed release.
Workarounds
- Set LIVEVIEW_ALLOWED_MODULES to the narrow list of modules containing mountable LiveView classes; note this is mitigation only, since pre-patch matching is startswith-based and import still precedes the subclass check
- Place the djust transport endpoints behind an authenticating reverse proxy that rejects anonymous WebSocket upgrades
- Remove or unload optional Python packages whose import performs sensitive side effects
# Configuration example: narrow the allowlist in Django settings.py
LIVEVIEW_ALLOWED_MODULES = [
"myapp.liveviews",
"myapp.admin.liveviews",
]
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

