ZeroHour

CVE-2026-61595

niche

Cross-tenant data disclosure in djust via fail-open tenant isolation on WebSocket/SSE

CVSS 3.1
7.7 high
EPSS
Published
()
Modified
AI analysis

The multi-tenancy module (djust.tenants) in djust enforced tenant isolation only on the HTTP request path: the current tenant was stored in threading.local() and set exclusively by the HTTP-only TenantMiddleware, so on live WebSocket/SSE connections get_current_tenant() returned None during mount and in every event handler. Because the tenant-aware QuerySet manager failed OPEN in that situation — returning the unfiltered queryset even when STRICT_MODE was enabled — any query issued over the live path returned rows from every tenant. An attacker with a low-privilege account in one tenant who holds a WebSocket/SSE connection can therefore read other tenants' data (high confidentiality impact, no integrity or availability impact; CVSS 3.1 score 7.7 with scope change). All deployments running djust versions before 1.0.7 that use the djust.tenants feature together with WebSocket/SSE live connections are affected; plain HTTP-only usage is not impacted. No public proof-of-concept, KEV listing, or in-the-wild exploitation is known, and fixed version 1.0.7 is available.

What to do: Upgrade to djust 1.0.7 immediately, as there is no workaround for the live WebSocket/SSE path. Keep STRICT_MODE enabled (the default) and resolve any system check S006 warnings if STRICT_MODE was disabled; after patching, review access logs for suspicious cross-tenant reads performed over WebSocket/SSE connections.

Affected
djust (PyPI project) djustall versions prior to 1.0.7 (when the djust.tenants multi-tenancy feature is used with WebSocket/SSE live paths)
Estimated exposure
nichelikely at most low thousands of deployments — djust is a niche pip package, and only the subset using multi-tenancy with WebSocket/SSE is vulnerable — Estimate based on djust's status as a young, low-adoption Django live-view framework on pip with no known large-scale deployments, further narrowed to deployments that enable the djust.tenants module and serve live WebSocket/SSE…

Order-of-magnitude estimate by the model from install counts, market share and public scan data it knows; verify before quoting.

Description

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 `get_current_tenant()` was always `None` during mount and every event handler — and the tenant-aware `QuerySet` manager failed OPEN (returned the unfiltered queryset, ignoring `STRICT_MODE`), disclosing every tenant's rows to whoever held the socket. `threading.local` was additionally shared across connections on the `sync_to_async` 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 `STRICT_MODE`); and system check S006 warns when `STRICT_MODE=False`. No known workarounds are available on the live path.

Ecosystems
pip
Weakness
CWE-636, CWE-862
Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
GHSA
GHSA-3492-cvg7-9mr2 (high)

In the news

No ingested article mentions this CVE yet.