Sep 16, 2026·7 min read·5 visits
Unauthenticated remote attackers can bypass Django view-level access controls to mount protected reactive views and execute state-changing event handlers via direct WebSocket or Server-Sent Events (SSE) connections.
An authorization bypass vulnerability exists in the djust framework (djust-org/djust) prior to version 1.0.7. The framework fails to enforce standard Django view-level authorization mechanisms, such as AccessMixins or dispatch decorators, when mounting reactive views over stateful transport layers (WebSockets and Server-Sent Events). Unauthenticated or low-privileged attackers can establish persistent connections to mount arbitrary protected views and execute state-changing event handlers.
The djust framework is designed to bring reactive, Server-Side Rendered (SSR) components inspired by Elixir's Phoenix LiveView to Django applications.
By combining Django's model-view structure with a high-performance Rust execution engine, djust enables developers to establish interactive, stateful browser-to-server connections. The request lifecycle consists of an initial HTTP Server-Side Rendering (SSR) phase followed by an upgrade to a stateful transport layer using WebSockets or Server-Sent Events (SSE).
Prior to version 1.0.7, a critical structural gap existed between these two transport states. Standard Django security practices rely on view-level attributes, decorators, and authentication mixins that execute during the standard HTTP dispatch phase. When a client upgrades the connection to establish a stateful WebSocket session, the view-level dispatch cycle is not re-executed, which leaves stateful endpoints vulnerable to direct access.
This vulnerability exposes a major attack surface across any deployment of djust that secures reactive views using standard Django middleware, mixins, or decorators. An unauthenticated attacker can target the WebSocket endpoint directly, completely bypassing the initial HTTP-based security gates. This allows unauthorized access to data and execution of backend actions that were intended to be restricted to authenticated administrative users.
The root cause of CVE-2026-61594 lies in how djust managed authorization checks during the stateful transport mount phase.
Standard Django views utilize the dispatch() method as a unified entry point for routing, executing decorators, and applying middleware checks. In contrast, the stateful WebSocket and SSE channels in vulnerable versions of djust relied on a decoupled, custom authorization function named check_view_auth.
This helper function did not replicate or trigger the standard Django dispatch() inheritance chain. Instead, check_view_auth inspected only a subset of authorization parameters and failed to recognize native Django mixins like LoginRequiredMixin, PermissionRequiredMixin, or UserPassesTestMixin. Furthermore, any decorators applied to the dispatch() method of a LiveView subclass—such as @method_decorator(login_required)—were never executed because the persistent socket handler directly instantiated the view and mounted its state without executing dispatch().
Consequently, an attacker who could not access the initial HTTP view (due to redirecting or rejecting authorization logic) could bypass the gate by establishing a raw WebSocket connection. By supplying the target view class's Python import path, the client could force the backend to initialize the restricted view. The djust server would then proceed to handle stateful event dispatches from the unauthenticated client, bypassing all intended access controls.
To understand the fix implemented in version 1.0.7, we must examine how the underlying verification logic was hardened.
In the vulnerable implementation, check_view_auth was blind to Django's standard authorization mixins. This allowed views inheriting from LoginRequiredMixin to be initialized blindly over stateful connections.
The patch introduced in version 1.0.7 addresses this by explicitly inspecting the target view class's inheritance hierarchy and executing the mixin requirements programmatically. It retrieves class-level configuration variables and mimics Django's security checks during the stateful handshake.
# Vulnerable check_view_auth implementation (Conceptual / Pre-1.0.7)
def check_view_auth(request, view_class):
# Only superficial checks were performed, completely ignoring
# Django's LoginRequiredMixin or customized dispatch() overrides.
if hasattr(view_class, 'djust_custom_gate'):
return view_class.djust_custom_gate(request)
return True # Silently defaults to authorized for standard mixins# Patched check_view_auth implementation (Conceptual / Post-1.0.7)
from django.contrib.auth.mixins import AccessMixin
def check_view_auth(request, view_class):
# Check for standard Django AccessMixin subclasses explicitly
if issubclass(view_class, AccessMixin):
# Ensure the request context has an authenticated user
if hasattr(view_class, 'login_required') and view_class.login_required:
if not request.user.is_authenticated:
return False
# Re-run custom user passes tests or permission checks
if hasattr(view_class, 'has_permission'):
# Resolve view instance to execute standard Django permission evaluations
view_instance = view_class()
view_instance.request = request
if not view_instance.has_permission():
return False
# Execute newly standardized declarative djust gates
if getattr(view_class, 'login_required', False) and not request.user.is_authenticated:
return False
return TrueIn addition to programmatic checks, the patch enforces static safety. The newly introduced system check djust.S004 evaluates views during application initialization. If a developer attempts to use an HTTP-specific @method_decorator on the dispatch method of a LiveView subclass, the system check raises an error and halts startup, preventing deployment of insecure configurations.
Exploiting this vulnerability does not require specialized tools or complex conditions.
An attacker only needs network access to the application's WebSocket or SSE path (typically hosted at /ws/ or /events/) and knowledge of the target view's import path. In most Django projects, these import paths follow predictable conventions (e.g., myapp.views.DashboardLiveView).
An attack begins by setting up a raw WebSocket client. Instead of browsing to /dashboard/, which redirects to a login prompt, the attacker establishes a connection directly to the persistent channel. The client then transmits a crafted mount payload over the active socket to instantiate the target view.
{
"type": "mount",
"view": "myapp.views.AdminControlLiveView",
"url": "/admin/control/"
}Upon receiving this packet, the vulnerable server executes check_view_auth. Since the logic is blind to the administrative decorators protecting dispatch(), the handshake succeeds. The backend responds by sending the initial server-side rendered state to the attacker over the WebSocket connection, effectively giving them full read access to the dashboard. The attacker can then issue reactive state-change commands by executing arbitrary event frames, such as deleting users or modifying global configurations.
The security impact of CVE-2026-61594 is severe, particularly for applications utilizing djust to build administrative interfaces or dashboards containing sensitive user data.
Because the vulnerability bypasses the primary line of defense in Django views, attackers can achieve unauthenticated remote code and state execution. Any stateful function exposed as a handler in a LiveView component is accessible to the attacker.
The integrity impact is high because these handlers are designed to perform database modifications, state updates, and resource creation. An unauthorized user can trigger any event-driven function defined in the view, leading to potential data corruption or unauthorized deletion. The confidentiality impact is also high, allowing malicious actors to inspect the visual components, configuration states, and underlying model records rendered by the target view.
With a CVSS v3.1 score of 9.1, this vulnerability represents a severe threat to applications exposed to the public internet. The attack complexity is low, requiring no authentication or user interaction. If a project relies on standard Django authentication mixins to secure reactive endpoints, they must be considered completely exposed until the application is patched.
The primary mitigation is upgrading to djust version 1.0.7 or later, which fully secures stateful channels and integrates with Django's native authorization systems.
To perform the upgrade, execute the following command in your project environment:
pip install --upgrade djust
If an immediate upgrade is not feasible, developers must transition their authorization logic away from standard Django HTTP decorators and custom dispatch() overrides on all LiveView subclasses. Instead, use djust-native, class-level declarative authorization properties. These properties are evaluated across both the standard HTTP rendering pipeline and the stateful transport layers:
# Secure configuration compatible with both pre and post 1.0.7 djust versions
from djust import LiveView
class SecureAdminView(LiveView):
# Enforced globally across HTTP, WebSockets, and SSE
login_required = True
permission_required = "app.view_dashboard"
template_name = "admin.html"Additionally, running python manage.py check is highly recommended. Post-upgrade, this will automatically detect and report any legacy, insecure dispatch authorization configurations that may still exist in your application, allowing developers to refactor them before they reach production.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
djust djust-org | < 1.0.7 | 1.0.7 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-862 |
| Attack Vector | Network (AV:N) |
| CVSS Score | 9.1 (Critical) |
| EPSS Score | Not listed |
| Impact | High (Confidentiality & Integrity) |
| Exploit Status | PoC / Verifiable |
| KEV Status | Not listed |
The software does not perform an authorization check when an actor attempts to access a resource or perform an action.
A cross-site scripting (XSS) vulnerability was identified in @nuxtjs/mdc prior to version 0.22.1. Gaps in the HTML/SVG attribute verification and URL protocol parsing allow unauthenticated remote attackers to bypass the application's sanitization routines. By embedding malicious SVG links or data-encoded iframe elements within Markdown, attackers can execute arbitrary JavaScript in the victim's browser context.
CVE-2026-58657 is a critical stored CSS injection vulnerability in Grav CMS's media processing pipeline. By exploiting improper sanitization of image dimensions in the resize helper, low-privileged users with page editing permissions can inject arbitrary CSS styles. This can lead to visual defacement, UI redressing, and indirect data exfiltration.
An authorization-decision over-inclusion vulnerability exists in the OpenFGA authorization engine. The flaw manifests within the `ListUsers` API evaluation path when evaluating complex relationship intersections containing exclusions. Under certain configurations involving wildcards, the exclusion is bypassed, leading to incorrect permission lists.
CVE-2026-61560 is a critical security vulnerability in the @zereight/mcp-gitlab Server-Sent Events (SSE) server. By utilizing default, unauthenticated route setups and exposing vulnerable administrative tools, remote attackers can execute path traversal attacks to read internal process variables and hijack GitLab operations.
A critical access control vulnerability in djust prior to 1.0.7 exposes diagnostic endpoints and remote method-invocation capabilities to unauthorized network actors. The vulnerability arises due to decoupling IP boundary validation into an opt-in middleware that was omitted from official configuration documentation, leaving views to rely solely on the status of Django's DEBUG flag.
The multi-tenant isolation mechanism in djust prior to version 1.0.7 fails open on active WebSocket and Server-Sent Events (SSE) connections. Because the tenant context is stored in thread-local variables and initialized exclusively via HTTP middleware, asynchronous event loops executing ASGI/WebSocket code paths do not carry the resolved tenant identifier. When queries are executed without this context, the default database manager fails open, allowing authenticated users of any tenant to query and read sensitive rows across all other tenant accounts.