CVE-2026-61595: djust: Multi-tenant isolation fails open on the WebSocket/SSE path, disclosing other tenants' data
Impact djust.tenants isolation was enforced only on the HTTP path. The current tenant was stored in threading.local() and set exclusively by the HTTP-only TenantMiddleware, so on the live (WebSocket/SSE) path getcurrenttenant() was always None during mount and every event handler — and the tenant-aware QuerySet manager failed OPEN (returned the unfiltered queryset, ignoring STRICTMODE), disclosing every tenant's rows to whoever held the socket. threading.local was additionally shared across connections on the synctoasync executor thread.
Patches Fixed in djust 1.0.7. Tenant storage moved to a contextvars.ContextVar (per async task); the resolved tenant is bound around WS/SSE mount and every dispatch; both managers scope the base queryset once and fail CLOSED (.none() under the default STRICTMODE); and system check S006 warns when STRICTMODE=False.
Workarounds No workaround on the live path short of upgrading.
Other sources
djust provides Phoenix LiveView-style reactive server-side rendering for Django with Rust-powered performance. Prior to version 1.0.7, djust.tenants isolation was enforced only on the HTTP path. The current tenant was stored in threading.local() and set exclusively by the HTTP-only TenantMiddleware, so on the live (WebSocket/SSE) path getcurrenttenant() was always None during mount and every event handler — and the tenant-aware QuerySet manager failed OPEN (returned the unfiltered queryset, ignoring STRICTMODE), disclosing every tenant's rows to whoever held the socket. threading.local was additionally shared across connections on the synctoasync executor thread. This issue is fixed in djust 1.0.7. Tenant storage moved to a contextvars.ContextVar (per async task); the resolved tenant is bound around WS/SSE mount and every dispatch; both managers scope the base queryset once and fail CLOSED (.none() under the default STRICTMODE); and system check S006 warns when STRICTMODE=False. No known workarounds are available on the live path.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/djustto a version that resolves this vulnerability.Fixed in 1.0.7 - Upgrade
Upgrade
djustto a version that resolves this vulnerability.Fixed in 1.0.7
Event History
Frequently Asked Questions
Who is exposed to this issue?
Deployments using djust.tenants with live WebSocket or SSE functionality are exposed if they run a version prior to 1.0.7. Any user who can hold a live socket may receive rows belonging to other tenants.
What does an attacker need to exploit it?
An attacker needs a low-privileged account and access to an affected WebSocket or SSE live path. No user interaction is required, and the vulnerable tenant-aware queryset behavior can return unfiltered data during mount and event handling.
Does the default strict-mode configuration prevent exposure?
No. On affected versions, the live-path queryset manager failed open and ignored STRICT_MODE because no current tenant was bound on the WebSocket/SSE path.
What should be done if patching is not immediately possible?
No known workaround is available for the live path. Upgrade to djust 1.0.7; until then, avoid exposing affected WebSocket or SSE tenant-facing functionality.
How can I determine whether my deployment is affected?
Check whether djust.tenants is used with WebSocket or SSE live features and whether the installed djust version is earlier than 1.0.7. Affected versions have tenant context set only through the HTTP-only TenantMiddleware, leaving the live path without a current tenant.