Sep 16, 2026·7 min read·23 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.
CVE-2026-118777 is a prototype pollution vulnerability (CWE-1321) in the Forge JavaScript cryptography and networking library (distributed on npm as node-forge) prior to version 1.4.1. The flaw resides in the forge.http client subsystem, where incoming HTTP cookie names and paths parsed from Set-Cookie response headers are stored directly into standard JavaScript objects without key validation or property isolation. By returning crafted Set-Cookie headers containing keys such as __proto__ or constructor, a malicious HTTP server can inject arbitrary properties into Object.prototype, attach attributes to the global Object constructor, or delete built-in prototype methods to cause an application-wide denial of service.
CVE-2026-118775 (GHSA-4642-5mcj-2rqw) is an integer overflow and validation flaw in the ASN.1 serialization module of Forge (node-forge) prior to version 1.4.1. The asn1.oidToDer() function fails to validate the range of the first two arcs of an Object Identifier (OID) and truncates the packed initial subidentifier to a single 8-bit integer. Applications that perform policy checks on untrusted OID strings before encoding them into Distinguished Encoding Rules (DER) format can be tricked into emitting DER bytes that correspond to a completely different, restricted OID.
CVE-2026-119194 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting versions 0.3.3 through 0.6.4. The flaw resides in the schemaless decoding routine ConstructedPayloadDecoderBase._decodeComponentsSchemaless used across BER, CER, and DER codecs. By sending an ASN.1 container populated with child components whose tag identifiers are separated by multiples of CPython's integer hash modulus (sys.hash_info.modulus), an unauthenticated attacker can force worst-case hash collisions in an unbounded Python set, degrading decoding performance from O(N) to O(N^2) and causing a Denial of Service (DoS).
CVE-2026-119195 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting all versions prior to 0.6.5. When decoding constructed strings or indefinite-length ANY types across BER, CER, and certain DER code paths, the payload decoders repeatedly concatenate incoming fragments onto an immutable bytes object using the += operator. Because Python bytes objects cannot be resized in-place, each fragment iteration allocates a new buffer and copies all previously accumulated bytes, resulting in quadratic O(N^2) time and memory copy complexity. An unauthenticated remote attacker can supply a highly fragmented ASN.1 stream to exhaust CPU cycles and stall application worker threads.
An algorithmic complexity vulnerability (CWE-407) in pyasn1 versions prior to 0.6.5 allows unauthenticated attackers to cause a Denial of Service (DoS) via crafted ASN.1 payloads. The flaw resides in the binary-encoded ASN.1 REAL mantissa deserialization routine within RealPayloadDecoder.valueDecoder. By performing iterative byte-string slicing and repeated bitwise shifts on a growing arbitrary-precision integer, the decoder exhibits quadratic time and memory allocation complexity relative to the mantissa length. Supplying a BER-, CER-, or DER-encoded payload with a large REAL mantissa causes excessive CPU consumption and blocks application worker processes.
A vulnerability classified under CWE-407 (Inefficient Algorithmic Complexity) exists in the pyasn1 library prior to version 0.6.5. When parsing constructed ASN.1 BIT STRING payloads under BER, CER, or schema-driven DER encoding rules, the BitStringPayloadDecoder repeatedly shifts and copies the entire accumulated bit value for each incoming fragment. Processing inputs with a large number of small constructed fragments induces quadratic CPU consumption, allowing unauthenticated remote attackers to cause a denial of service via resource exhaustion during the initial decoding phase.