CVE-2026-61595 Overview
CVE-2026-61595 is a tenant isolation flaw in djust, a Django framework that provides Phoenix LiveView-style reactive server-side rendering with Rust-powered performance. Versions prior to 1.0.7 enforce tenant isolation only on the HTTP path. On the WebSocket and Server-Sent Events (SSE) live path, get_current_tenant() returns None, and the tenant-aware QuerySet manager fails open by returning an unfiltered queryset. Any authenticated user holding a live socket can read rows belonging to every tenant. The issue is tracked under CWE-636: Not Failing Securely (Failing Open).
Critical Impact
Cross-tenant data disclosure across every model backed by the tenant-aware manager on djust live connections.
Affected Products
- djust framework versions prior to 1.0.7
- Applications using djust.tenants multi-tenant isolation
- Deployments exposing djust WebSocket or SSE live endpoints
Discovery Timeline
- 2026-09-16 - CVE-2026-61595 published to NVD
- 2026-09-16 - Last updated in NVD database
Technical Details for CVE-2026-61595
Vulnerability Analysis
The vulnerability affects the djust.tenants module responsible for scoping queries per tenant. The current tenant identity is stored in threading.local() and set exclusively by the HTTP-only TenantMiddleware. On live connections handled through WebSocket or SSE, that middleware never runs. The tenant-aware QuerySet manager checks for a resolved tenant and, when none is present, returns the unfiltered base queryset instead of denying access.
A second defect compounds the flaw. Because threading.local is shared across connections on the sync_to_async executor thread pool, tenant state can leak between concurrent live sessions running on the same worker thread. The result is that any user who establishes a live connection can retrieve rows belonging to unrelated tenants during mount and every event handler dispatch.
Root Cause
The root cause is a fail-open design in the tenant-aware manager combined with an incorrect storage primitive. The manager ignored STRICT_MODE when the tenant context was unset, treating a missing tenant as "no filter" rather than "no access." Storing tenant identity in threading.local() also fails to isolate concurrent async tasks that reuse executor threads.
Attack Vector
An authenticated user with any tenant assignment opens a WebSocket or SSE connection to a djust live view. During mount and each subsequent event, the tenant-aware manager evaluates its base queryset without a tenant filter. The client receives records from all tenants exposed through the affected live view. Exploitation requires no elevated privileges beyond a valid low-privilege session capable of establishing the live connection.
No verified proof-of-concept code is published. Refer to the GitHub Security Advisory GHSA-3492-cvg7-9mr2 for maintainer-authored technical details.
Detection Methods for CVE-2026-61595
Indicators of Compromise
- WebSocket or SSE connections to djust live endpoints returning payloads containing identifiers from tenants unrelated to the authenticated user.
- Application logs showing get_current_tenant() returning None during live view mount or event dispatch on djust versions prior to 1.0.7.
- Unusually large result sets from tenant-scoped models when accessed through live views compared to equivalent HTTP endpoints.
Detection Strategies
- Inventory Python dependencies for djust<1.0.7 using pip list or software composition analysis tooling.
- Enable the djust system check S006 after upgrading to surface deployments still running with STRICT_MODE=False.
- Compare row counts returned by live view queries against the tenant scope expected for the authenticated principal.
Monitoring Recommendations
- Log tenant identity resolution at the entry point of every WebSocket and SSE consumer and alert when it resolves to None.
- Monitor egress volume on live endpoints for anomalous data extraction consistent with tenant enumeration.
- Correlate authenticated user identity with tenant IDs present in outbound payloads to identify cross-tenant access.
How to Mitigate CVE-2026-61595
Immediate Actions Required
- Upgrade djust to version 1.0.7 or later across all environments hosting the framework.
- Confirm STRICT_MODE is enabled so tenant-aware managers fail closed with .none() when no tenant is bound.
- Audit application logs and data access records for cross-tenant reads originating from live view sessions since deployment.
Patch Information
The fix ships in djust 1.0.7. Tenant storage moves from threading.local() to a contextvars.ContextVar scoped per async task. The resolved tenant is bound around WebSocket and SSE mount and every dispatch. Both managers scope the base queryset once and fail closed by returning .none() under the default STRICT_MODE. System check S006 warns operators when STRICT_MODE=False. Release notes are available at the djust v1.0.7 release page.
Workarounds
- No workarounds are available on the live path according to the maintainer advisory; upgrading to 1.0.7 is required.
- As a temporary containment measure, disable djust WebSocket and SSE endpoints at the reverse proxy until the upgrade is applied.
- Restrict live view routes to a single-tenant deployment topology to reduce blast radius while patching is scheduled.
# Upgrade djust to the fixed release
pip install --upgrade 'djust>=1.0.7'
# Verify STRICT_MODE is enabled in Django settings
grep -R "DJUST_TENANTS" ./settings/
# Run Django system checks to surface S006 warnings
python manage.py check
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

