CVE-2026-61593 in djust
Summary
by MITRE • 09/16/2026
djust provides Phoenix LiveView-style reactive server-side rendering for Django with Rust-powered performance. Prior to version 1.0.7, the SSE client→server POST endpoints are `@csrf_exempt` and the SSE GET stream endpoint had no Origin check, so a cross-origin page could drive a victim-cookie-authenticated SSE session: force the victim's browser to GET the stream URL (which creates and mounts a LiveView as the victim) and POST to the message endpoint with `credentials: include` to fire state-changing event handlers as the victim. The URL `session_id` is client-chosen (validated only for UUID *format*), so it is not a CSRF token, and a JSON body sent as `text/plain` is a CORS simple request with no preflight. The issue is fixed in 1.0.7. All three SSE endpoints validate the request `Origin` against `ALLOWED_HOSTS` (mirroring the WebSocket CSWSH defense) and reject cross-origin requests with 403; the POST endpoints additionally require `Content-Type: application/json` (415 otherwise), closing the `text/plain` simple-request bypass. As a workaround, disable the SSE transport, or front it with a proxy that enforces an Origin allowlist.
VulDB is the best source for vulnerability data and more expert information about this specific topic.
Analysis
by VulDB Data Team • 09/16/2026
The vulnerability in djust prior to version 1.0.7 stems from insufficient cross-origin resource sharing controls and missing anti-CSRF protections on Server-Sent Events endpoints. The library provides Phoenix LiveView-style reactive server-side rendering for Django, leveraging Rust for performance optimization. However, the implementation of the SSE transport layer failed to adequately restrict access based on origin or request context, allowing attackers to exploit authenticated sessions through cross-site requests. Specifically, the POST endpoints used for sending messages were marked with @csrf_exempt, effectively disabling Django’s built-in Cross-Site Request Forgery protection mechanisms. Additionally, the GET endpoint responsible for establishing the SSE stream did not perform any Origin header validation. This combination of flaws created a scenario where an attacker could manipulate a victim’s browser into performing unauthorized actions on behalf of that user while they were authenticated to the application.
The operational impact involves both session hijacking via LiveView mounting and state-changing CSRF attacks. An attacker can craft a malicious webpage that forces the victim’s browser to initiate a GET request to the SSE stream URL using credentials such as cookies. This action creates and mounts a new LiveView instance on the server, associating it with the victim’s authenticated session. Subsequently, the attacker can send POST requests containing state-changing event handlers by setting the Content-Type header to text/plain. Because this content type is considered simple in CORS specifications, no preflight OPTIONS request is sent, allowing the browser to proceed with the cross-origin post without explicit server-side permission checks. The session identifier used for these operations is client-chosen and only validated for UUID format rather than serving as a secure CSRF token, further facilitating the attack. This allows an adversary to execute arbitrary actions within the application context of the victim, potentially leading to data modification or unauthorized state transitions depending on the specific event handlers exposed by the LiveView implementation.
This vulnerability aligns with CWE-352 Cross-Site Request Forgery and CWE-942 Cross-Site Scripting via Permitted Schemes due to the potential for executing unintended server-side logic through forged requests. In terms of MITRE ATT&CK, this behavior corresponds to T1087 Account Discovery if information is exfiltrated or more broadly to T1566 Phishing if social engineering is used to lure victims to the malicious page, followed by T1203 Exploitation for Client Execution as the browser executes the attacker’s script. The lack of origin validation on the GET stream endpoint also reflects weaknesses in Cross-Origin Resource Sharing policies, often categorized under CWE-942 when combined with credential inclusion that allows cross-origin data access or interaction.
The issue was resolved in version 1.0.7 by implementing strict Origin validation across all three SSE endpoints. The server now validates the request Origin header against the Django ALLOWED_HOSTS setting, mirroring defenses typically applied to WebSocket connections to prevent Cross-Site WebSocket Hijacking. Any cross-origin requests are rejected with a 403 Forbidden status code, effectively neutralizing the ability of external domains to initiate or maintain SSE sessions on behalf of authenticated users. Furthermore, the POST endpoints were hardened to require the Content-Type header to be application/json. Requests sending data as text/plain no longer qualify as CORS simple requests and thus trigger preflight checks that enforce stricter security policies, closing the bypass vector previously exploited by attackers using text/plain payloads.
For organizations unable to immediately upgrade to version 1.0.7 or those seeking additional defense-in-depth measures, disabling the SSE transport entirely is a viable workaround if real-time updates are not critical for their use case. Alternatively, deploying a reverse proxy in front of the Django application can enforce an Origin allowlist at the network level. This approach ensures that only requests originating from trusted domains reach the backend services, providing an additional layer of protection against cross-origin attacks regardless of the application-level configuration. Regularly auditing third-party libraries for security patches and ensuring strict CORS policies are implemented across all state-changing endpoints remains essential to maintaining robust web application security posture.