Impact The djust live transport resolves the LiveView to mount from a client-supplied dotted path by calling import(modulepath, ...). The module is imported — running its top-level code (import side effects) — before the framework checks that the resolved object is a LiveView subclass and before any per-view authentication. The LIVEVIEWALLOWEDMODULES allowlist that should contain this is fail-open (if allowedmodules: — skipped when the setting is unset, the framework default) and uses loose startswith matching.
An unauthenticated WebSocket client (the WS handshake does not require auth; per-view auth runs only after import + instantiate) can therefore send a mount / liveredirectmount / urlchange frame (or an SSE mount) with view = "<any.importable.module>.AnyName" and cause the server to import — and execute the top-level code of — any importable Python module by name.
Consequences: server-side execution of arbitrary importable modules' import-time side effects by an unauthenticated client (effectively RCE-by-proxy on any host that has a side-effectful importable module), denial of service (import bombs / expensive dependency trees), and a module/class enumeration oracle via distinct error strings.
Reproduced end-to-end: an unauthenticated WebsocketCommunicator mount frame with the allowlist unset imported and executed a sentinel non-LiveView module before the "not a LiveView subclass" rejection.
Affected code - python/djust/websocket.py handlemount (import of the client view) - python/djust/runtime.py ViewRuntime.dispatchmount / instantiateview (SSE + urlchange path) - python/djust/sse.py SSE mount
Threat-model entry T4 (docs/audits/websocket-auth-2026-06.md) previously noted the default-open allowlist but understated the impact as mere LiveView-class probing; the real primitive is arbitrary-module import + top-level code execution, independent of whether the target is a LiveView.
Patches Fixed by a fail-closed resolution gate (djust.viewresolution.isviewimportallowed): a client view path resolves only if (a) its module is already loaded (sys.modules — so resolving runs no new code; URL-routed views loaded by URLconf at startup keep working with zero config) or (b) it matches LIVEVIEWALLOWEDMODULES on a module-segment boundary (explicit opt-in for lazily-imported views). The gate runs before import at all three sinks (+ defense-in-depth inside instantiateview).
Workarounds Set LIVEVIEWALLOWEDMODULES to the narrow list of modules that contain your mountable LiveView classes. (Note: pre-patch the allowlist is startswith-matched and the import still precedes the subclass check, so this is mitigation, not a complete fix.)
References Reproducer + finding writeup retained privately by the maintainer.
Impact The WebSocket handlemount and ViewRuntime.buildrequest rebuild an HttpRequest via RequestFactory().get(...) with no HTTPHOST, so request.gethost() defaulted to "testserver" on the live path. Host/subdomain/domain TenantResolvers then misresolved the tenant — None on the live path while the HTTP path resolved correctly. With STRICTMODE=False the tenant-scoped managers returned unscoped rows (cross-tenant disclosure); with the default they returned an empty queryset (broken tenancy).
Patches Fixed in djust 1.0.7. The handshake Host is extracted from the ASGI scope, validated against ALLOWEDHOSTS (the same logic as the CSWSH Origin gate, parsed with Django's splitdomainport so malformed Hosts are rejected at the boundary), and propagated — with the TLS scheme — into the reconstructed request, so live-path tenant resolution matches HTTP exactly.
Workarounds No workaround on the live path short of upgrading. Most exposed when combined with STRICTMODE=False.
Impact When a Django Model instance is assigned to a public view attribute, djust serialized it to the client with no sensitive-field denylist — sending fields such as password (the hash), privilege flags (e.g. isstaff / issuperuser), tokens, and other PII to the browser. Because exposing model objects to templates is a normal djust pattern, this could leak credentials/PII without the developer realizing the full object crossed the wire.
Patches Fixed in djust 1.0.7. Model serialization applies a secure-by-default sensitive-field denylist (password/hash/token/secret-style fields and known privilege flags are withheld) with an identity-subset fallback.
Workarounds Keep Model instances on private attributes and expose only the specific fields needed, until patched.