Sep 16, 2026·5 min read·21 visits
A validation omission in djust allows attackers to hijack reactive user sessions via cross-site requests, mounting unauthorized server-side components and executing state-changing handlers.
CVE-2026-61593 is a high-severity Cross-Site Request Forgery (CSRF) vulnerability discovered in the Server-Sent Events (SSE) transport layer of djust, an open-source framework that implements Phoenix LiveView-style reactive server-side rendering for Django applications. Before version 1.0.7, a lack of origin verification on the SSE stream endpoint, combined with @csrf_exempt decorators on message POST endpoints, allowed an attacker to hijack active client sessions through cross-origin interactions.
The djust library provides real-time reactive UI rendering in Django applications by maintaining a continuous state synchronization channel. This channel is split into two main endpoints: a Server-Sent Events (SSE) GET stream for downstream updates and a series of POST endpoints for client-to-server action messages.
Because standard web browsers automatically send authentication cookies along with credentialed cross-origin GET requests, the lack of origin validation on the SSE stream endpoint allowed malicious web pages to initiate sessions on behalf of authenticated users.
At the same time, the POST message endpoints were decorated with @csrf_exempt to simplify JSON transmission. This combined structure meant that once a session was established, an attacker could dispatch cross-origin requests to trigger server-side handlers without triggering Django's built-in CSRF defenses.
The underlying vulnerability results from three distinct architecture design flaws. First, the GET endpoint used to establish the SSE stream did not perform any validation on the HTTP Origin header, allowing any external origin to request connection initialization with credentials.
Second, the framework relied on client-generated UUIDs as the reactive session identifiers rather than server-issued, cryptographically secure tokens. The server validated the session ID format via regular expression matching but did not verify whether the session ID was created by an authorized handshake.
Third, the client-to-server POST endpoints accepted request bodies with a Content-Type header set to text/plain. Browser security policies allow cross-origin POST requests with simple content types like text/plain to bypass CORS preflight checks, meaning the browser sent the payload and the session cookies directly to the target server.
The vulnerable routing and view logic did not inspect incoming headers before instantiating or finding the active LiveView session.
# Vulnerable Implementation (< 1.0.7)
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse, JsonResponse
import json
@csrf_exempt
def sse_message(request, session_id):
# VULNERABILITY 1: Bypasses CSRF checks entirely
# VULNERABILITY 2: Does not validate request.headers.get('Origin')
# VULNERABILITY 3: Does not enforce application/json Content-Type
payload = json.loads(request.body)
trigger_event(session_id, payload)
return JsonResponse({"status": "success"})The patched version introduces strict origin validation against the configured django.conf.settings.ALLOWED_HOSTS and mandates the application/json content type.
# Patched Implementation (>= 1.0.7)
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponseForbidden, HttpResponse
from django.conf import settings
from urllib.parse import urlparse
@csrf_exempt
def sse_message_patched(request, session_id):
origin = request.headers.get('Origin')
if origin:
parsed_origin = urlparse(origin).netloc
# Fix 1: Validate that the origin matches allowed hosts
if parsed_origin not in settings.ALLOWED_HOSTS:
return HttpResponseForbidden("Invalid Origin")
# Fix 2: Require strict content-type to trigger CORS preflight
content_type = request.content_type
if content_type != 'application/json':
return HttpResponse("Unsupported Media Type", status=415)
payload = json.loads(request.body)
trigger_event(session_id, payload)
return JsonResponse({"status": "success"})An attacker can exploit this vulnerability by hosting a malicious page and enticing an authenticated user of the vulnerable application to visit it. The attack requires no special privileges beyond web network access.
First, the malicious page runs JavaScript that opens a credentialed GET request to the djust SSE stream path, providing a random but valid UUID. The server parses the victim's session cookies, authenticates the request, and initializes a LiveView state linked to that UUID.
Second, the attacker sends a POST request containing the event handler execution payload to the message endpoint. The request is sent with the Content-Type header set to text/plain to bypass the browser's CORS preflight rules, while still delivering JSON content which the server processes without CSRF validation.
The direct impact is complete control over the victim's application session. An attacker can trigger any state-changing action that the active Django user is authorized to perform, including account modifications, data entry, and sensitive administrative tasks.
Because the SSE endpoint can also leak state updates back to the client-side channel under specific conditions, the confidentiality of user-specific state data is compromised. The CVSS score of 8.1 reflects high integrity and confidentiality impacts combined with low attack complexity and no requirement for prior privileges.
The primary remediation path is upgrading the djust package to version 1.0.7 or later, which implements strict Origin header matching and Content-Type enforcement.
If upgrading is not immediately possible, deploy a reverse proxy or Web Application Firewall (WAF) in front of the application. The proxy must be configured to inspect all incoming requests destined for the djust SSE paths and block any request where the Origin header does not match the application's domain, or where a POST request has a Content-Type other than application/json.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/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-352: Cross-Site Request Forgery (CSRF) |
| Attack Vector | Network |
| CVSS v3.1 Score | 8.1 |
| Impact | High (Confidentiality, Integrity) |
| Exploit Status | poc |
| KEV Status | Not Listed |
The web application does not, or cannot, sufficiently verify whether a well-formed, valid, consistent request was intentionally sent by the user.
CVE-2026-118773 (GHSA-3g3m-2fjr-6pw4) is an uncontrolled resource consumption vulnerability in the node-glob npm package affecting versions 9.0.0 through 14.0.1. Due to missing return statements in the AbortSignal check routines within the directory traversal walker, aborted operations reject the caller promise as expected but continue executing background filesystem reads and pattern matching. Applications that rely on AbortSignal or AbortSignal.timeout() to enforce execution budgets on user-influenced glob operations remain susceptible to CPU, event loop, and disk I/O exhaustion.
CVE-2026-118764 (also tracked as GHSA-g3hv-75wg-m249) is an asymmetric resource consumption vulnerability (CWE-405) in the npm package minimatch prior to version 11.0.1. When pattern compilation is invoked with an optimizationLevel of 2 or higher, the internal preprocessing functions firstPhasePreProcess() and secondPhasePreProcess() in src/index.ts perform unbounded pattern splitting and quadratic pairwise deduplication. An attacker supplying a crafted glob string containing repeated **/.. segments can induce a combinatorial explosion of pattern permutations followed by an O(M^2) comparison routine, blocking the Node.js event loop and exhausting process memory.
A regular expression denial of service (ReDoS) vulnerability exists in @hapi/content from version 3.0.6 prior to 6.0.3. The Content.disposition() function utilizes an unanchored parameter-name regular expression inside a global replacement scan. When processing a Content-Disposition header parameter containing a long token lacking an equals sign, the JavaScript regular expression engine undergoes quadratic O(N^2) backtracking. Because @hapi/content is invoked by @hapi/pez during multipart/form-data request parsing, unauthenticated remote attackers can send a crafted multipart request to any Hapi route with multipart payload parsing enabled, starving the single-threaded Node.js event loop.
A Regular Expression Denial of Service (ReDoS) vulnerability exists in the joi schema description and data validation library for JavaScript. When validating multiple email addresses using the Joi.string().email({ multiple: true }) configuration, the library compiles a separator regular expression with an unanchored greedy leading whitespace quantifier. Supplying an input string containing a long sequence of whitespace characters without the expected delimiter triggers quadratic time complexity during String.prototype.split execution, blocking the single-threaded Node.js event loop.
CVE-2026-119205 (GHSA-mfr5-77xh-9j7h) is a Denial of Service (DoS) vulnerability in pypdf prior to version 6.21.4. The flaw occurs during the cloning or duplication of nested PDF dictionary structures. Because the cycle-detection algorithm within DictionaryObject._clone() tracked generated destination object references rather than the original source indirect references, cyclic reference graphs in source PDFs evaded detection, resulting in an infinite loop and CPU exhaustion.
CVE-2026-119204 (also tracked as GHSA-cggf-277g-3q54) is a Denial of Service (DoS) vulnerability in pypdf prior to version 6.21.4. The vulnerability stems from uncontrolled resource consumption (CWE-400) during the flattening of a PDF document's page tree. By supplying a compact PDF containing a hierarchical amplification structure of shared `/Pages` and `/Page` nodes with dense dictionary entries or inherited resources, an unauthenticated attacker can cause pypdf to copy millions of dictionary entries into individual `PageObject` instances without enforcing a document-wide entry budget. This triggers severe heap memory exhaustion and process termination via Out-Of-Memory (OOM) kills.