{"id":"CVE-2026-55571","aliases":["EUVD-2026-65600","GHSA-xx4j-w367-7247","PYSEC-2026-3829"],"status":"published","title":"djust authentication bypass: a login_required / on_mount LiveView mount redirect does not close the WebSocket, allowing an unauthenticated client to dispatch event-handler calls","description":"djust provides Phoenix LiveView-style reactive server-side rendering for Django with Rust-powered performance. Prior to 1.0.4, LiveViewConsumer.handle_mount sends a `{\"type\":\"navigate\",\"to\":...}` frame when login_required, permission_required, or a redirecting on_mount hook denies a LiveView mount, but returns without closing the WebSocket or clearing self.view_instance. A browser follows the redirect, but a raw WebSocket client can ignore it and retain the mounted socket. Because LiveViewConsumer.handle_event does not recheck authentication or authorization, the client can send `{\"type\":\"event\",...}` frames that invoke @event_handler methods without an authenticated session, including through handle_live_redirect_mount, enabling unauthorized sensitive reads or mutations. This issue is fixed in version 1.0.4.","severity":{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00505,"percentile":0.43492,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-285","CWE-306"],"published":"2026-08-25T16:05:49Z","modified":"2026-10-28T02:30:48Z","fixes":[{"ecosystem":"PyPI","package":"djust","fixed_in":["1.0.4"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"djust","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.0.4"}]}]},{"source":"osv","ecosystem":"PyPI","package":"djust","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.0.4"}]}],"versions":["0.1.0","0.1.2","0.1.3","0.1.4","0.1.5","0.1.6","0.1.7","0.1.8","0.1.9","0.2.0","0.2.1","0.2.2","0.3.0","0.3.1","0.3.2","0.3.4","0.3.5","0.3.6","0.3.7","0.3.8","0.4.0","0.4.1","0.4.2","0.4.3","0.4.4","0.9.0","0.9.1","0.9.2","0.9.4","0.9.5","0.9.6","0.9.7","1.0.0","1.0.0rc1","1.0.0rc10","1.0.0rc11","1.0.0rc12","1.0.0rc13","1.0.0rc14","1.0.0rc15","1.0.0rc16","1.0.0rc17","1.0.0rc18","1.0.0rc2","1.0.0rc3","1.0.0rc4","1.0.0rc6","1.0.0rc7","1.0.0rc8","1.0.0rc9","1.0.1","1.0.1rc1","1.0.2","1.0.2rc1","1.0.2rc2","1.0.2rc3","1.0.3","1.0.3rc1","1.0.3rc2","1.0.4rc1"]},{"source":"osv","ecosystem":"PyPI","package":"djust","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.0.4"}]}],"versions":["0.1.0","0.1.2","0.1.3","0.1.4","0.1.5","0.1.6","0.1.7","0.1.8","0.1.9","0.2.0","0.2.1","0.2.2","0.3.0","0.3.1","0.3.2","0.3.4","0.3.5","0.3.6","0.3.7","0.3.8","0.4.0","0.4.1","0.4.2","0.4.3","0.4.4","0.9.0","0.9.1","0.9.2","0.9.4","0.9.5","0.9.6","0.9.7","1.0.0","1.0.0rc1","1.0.0rc10","1.0.0rc11","1.0.0rc12","1.0.0rc13","1.0.0rc14","1.0.0rc15","1.0.0rc16","1.0.0rc17","1.0.0rc18","1.0.0rc2","1.0.0rc3","1.0.0rc4","1.0.0rc6","1.0.0rc7","1.0.0rc8","1.0.0rc9","1.0.1","1.0.1rc1","1.0.2","1.0.2rc1","1.0.2rc2","1.0.2rc3","1.0.3","1.0.3rc1","1.0.3rc2","1.0.4rc1"]}],"products":[{"vendor":"djust-org","product":"djust"}],"references":[{"url":"https://github.com/djust-org/djust/security/advisories/GHSA-xx4j-w367-7247","tags":["x_refsource_CONFIRM","exploit","advisory","web"]},{"url":"https://github.com/djust-org/djust/pull/1780","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/djust-org/djust/commit/1ae8aa9246b80477de7ddc4d90319a3b267bef04","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/djust-org/djust/releases/tag/v1.0.4","tags":["x_refsource_MISC","web"]},{"url":"https://github.com/advisories/GHSA-xx4j-w367-7247","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/55xxx/CVE-2026-55571.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-55571","tags":["advisory"]},{"url":"https://github.com/djust-org/djust","tags":["package"]},{"url":"https://pypi.org/project/djust","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-55571","title":"djust authentication bypass: a login_required / on_mount LiveView mount redirect does not close the WebSocket, allowing an unauthenticated client to dispatch event-handler calls","description":"djust provides Phoenix LiveView-style reactive server-side rendering for Django with Rust-powered performance. Prior to 1.0.4, LiveViewConsumer.handle_mount sends a `{\"type\":\"navigate\",\"to\":...}` frame when login_required, permission_required, or a redirecting on_mount hook denies a LiveView mount, but returns without closing the WebSocket or clearing self.view_instance. A browser follows the redirect, but a raw WebSocket client can ignore it and retain the mounted socket. Because LiveViewConsumer.handle_event does not recheck authentication or authorization, the client can send `{\"type\":\"event\",...}` frames that invoke @event_handler methods without an authenticated session, including through handle_live_redirect_mount, enabling unauthorized sensitive reads or mutations. This issue is fixed in version 1.0.4.","status":"published","published":"2026-08-25T16:05:49.069Z","modified":"2026-08-25T17:56:03.253Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high","assessor":"cna"}],"cwes":["CWE-285","CWE-306"],"updated_at":"2026-11-02T14:20:11.925815Z"}],"euvd":[{"id":"EUVD-2026-65600","description":"djust provides Phoenix LiveView-style reactive server-side rendering for Django with Rust-powered performance. Prior to 1.0.4, LiveViewConsumer.handle_mount sends a `{\"type\":\"navigate\",\"to\":...}` frame when login_required, permission_required, or a redirecting on_mount hook denies a LiveView mount, but returns without closing the WebSocket or clearing self.view_instance. A browser follows the redirect, but a raw WebSocket client can ignore it and retain the mounted socket. Because LiveViewConsumer.handle_event does not recheck authentication or authorization, the client can send `{\"type\":\"event\",...}` frames that invoke @event_handler methods without an authenticated session, including through handle_live_redirect_mount, enabling unauthorized sensitive reads or mutations. This issue is fixed in version 1.0.4.","status":"published","published":"2026-08-25T16:05:49Z","modified":"2026-08-25T17:56:03Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high"}],"updated_at":"2026-11-02T18:01:32.174502Z"}],"ghsa":[{"id":"GHSA-xx4j-w367-7247","title":"djust authentication bypass: a login_required / on_mount LiveView mount redirect does not close the WebSocket, allowing an unauthenticated client to dispatch event-handler calls","description":"### Impact\n\ndjust's `LiveViewConsumer` mounts a `LiveView` over a WebSocket. When a view is gated (`login_required` / `permission_required`, or an `on_mount` hook that returns a redirect) and the connecting user is not authorized, the consumer sent the client a `{\"type\":\"navigate\",\"to\":...}` redirect frame and then `return`ed — **without closing the socket and without clearing `self.view_instance`**. Only the `PermissionDenied` branch closed the connection (`close(4403)`).\n\nA real browser obeys the navigate frame and leaves, hiding the problem. A **raw WebSocket client that ignores the redirect** keeps an open, mounted socket. Because `handle_event` did not re-check authentication/authorization after mount, that client could then send `{\"type\":\"event\", ...}` frames and invoke any `@event_handler` method on the gated view **with no authenticated session** — an authentication bypass on the live mutation path.\n\n**Who is affected:** apps that expose `LiveView`s gated by `login_required` / `permission_required` / a redirecting `on_mount` hook, where the gated view's event handlers perform sensitive reads or mutations and do not independently re-verify the user. Exploitation requires a non-browser WebSocket client and knowledge (or enumeration) of the view path and event names.\n\n### Patches\n\nFixed in **djust 1.0.4** (commit `1ae8aa9`, PR #1780). Both the auth-redirect and `on_mount`-hook-redirect branches of `handle_mount` now send the navigate frame **and then `close(code=4403)` and clear `self.view_instance`**, mirroring the existing `PermissionDenied` branch. Public / authorized mounts are unchanged. The same path is reachable via `handle_live_redirect_mount` (which delegates to `handle_mount`) and is covered by the same fix.\n\n1.0.4 also adds an opt-in defense-in-depth control, `LIVEVIEW_CONFIG['reauth_on_event'] = True` (default OFF), which re-resolves the user from the session and re-runs the view's auth check on **every** event for gated views.\n\n### Workarounds\n\nUpgrade to 1.0.4. If you cannot upgrade immediately, on affected versions ensure that **every `@event_handler` on a gated `LiveView` independently verifies the request user is authenticated and authorized** (e.g. check `request.user.is_authenticated` / permissions at the top of each handler), since the framework does not re-check after mount on `\u003c 1.0.4`. Alternatively, override the consumer's `handle_mount` to `await self.close(code=4403)` after emitting an auth redirect.\n\n### Proof of concept\n\nUsing Channels' `WebsocketCommunicator` against `LiveViewConsumer.as_asgi()` with an **anonymous** scope, mount a `login_required` view: the server emits a `navigate` frame but the socket stays open. Sending a subsequent `{\"type\":\"event\", \"handler\":\"\u003cmutating_handler\u003e\", ...}` frame reaches the handler and executes it without an authenticated session. On 1.0.4 the socket is closed with code `4403` immediately after the redirect and the event frame is rejected. (Regression test: `tests/test_ws_auth_close_socket.py`.)\n\n### Credits\n\nDiscovered internally during the djust v1.1.0 WebSocket-auth security review.","status":"published","published":"2026-08-25T16:06:31Z","modified":"2026-08-25T16:06:33Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high"}],"cwes":["CWE-285","CWE-306"],"updated_at":"2026-11-02T14:41:05.994358Z"}],"nvd":[{"id":"CVE-2026-55571","description":"djust provides Phoenix LiveView-style reactive server-side rendering for Django with Rust-powered performance. Prior to 1.0.4, LiveViewConsumer.handle_mount sends a `{\"type\":\"navigate\",\"to\":...}` frame when login_required, permission_required, or a redirecting on_mount hook denies a LiveView mount, but returns without closing the WebSocket or clearing self.view_instance. A browser follows the redirect, but a raw WebSocket client can ignore it and retain the mounted socket. Because LiveViewConsumer.handle_event does not recheck authentication or authorization, the client can send `{\"type\":\"event\",...}` frames that invoke @event_handler methods without an authenticated session, including through handle_live_redirect_mount, enabling unauthorized sensitive reads or mutations. This issue is fixed in version 1.0.4.","status":"published","published":"2026-08-25T17:17:32.547Z","modified":"2026-09-09T21:07:31.353Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high","assessor":"secondary"}],"cwes":["CWE-285","CWE-306"],"updated_at":"2026-11-02T14:12:41.347728Z"}],"osv":[{"id":"CVE-2026-55571","title":"djust authentication bypass: a login_required / on_mount LiveView mount redirect does not close the WebSocket, allowing an unauthenticated client to dispatch event-handler calls","description":"djust provides Phoenix LiveView-style reactive server-side rendering for Django with Rust-powered performance. Prior to 1.0.4, LiveViewConsumer.handle_mount sends a `{\"type\":\"navigate\",\"to\":...}` frame when login_required, permission_required, or a redirecting on_mount hook denies a LiveView mount, but returns without closing the WebSocket or clearing self.view_instance. A browser follows the redirect, but a raw WebSocket client can ignore it and retain the mounted socket. Because LiveViewConsumer.handle_event does not recheck authentication or authorization, the client can send `{\"type\":\"event\",...}` frames that invoke @event_handler methods without an authenticated session, including through handle_live_redirect_mount, enabling unauthorized sensitive reads or mutations. This issue is fixed in version 1.0.4.","status":"published","published":"2026-08-25T16:05:49.069Z","modified":"2026-10-28T02:30:48.503438619Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high"}],"cwes":["CWE-285","CWE-306"],"updated_at":"2026-11-02T15:45:11.22012Z"},{"id":"GHSA-xx4j-w367-7247","title":"djust authentication bypass: a login_required / on_mount LiveView mount redirect does not close the WebSocket, allowing an unauthenticated client to dispatch event-handler calls","description":"### Impact\n\ndjust's `LiveViewConsumer` mounts a `LiveView` over a WebSocket. When a view is gated (`login_required` / `permission_required`, or an `on_mount` hook that returns a redirect) and the connecting user is not authorized, the consumer sent the client a `{\"type\":\"navigate\",\"to\":...}` redirect frame and then `return`ed — **without closing the socket and without clearing `self.view_instance`**. Only the `PermissionDenied` branch closed the connection (`close(4403)`).\n\nA real browser obeys the navigate frame and leaves, hiding the problem. A **raw WebSocket client that ignores the redirect** keeps an open, mounted socket. Because `handle_event` did not re-check authentication/authorization after mount, that client could then send `{\"type\":\"event\", ...}` frames and invoke any `@event_handler` method on the gated view **with no authenticated session** — an authentication bypass on the live mutation path.\n\n**Who is affected:** apps that expose `LiveView`s gated by `login_required` / `permission_required` / a redirecting `on_mount` hook, where the gated view's event handlers perform sensitive reads or mutations and do not independently re-verify the user. Exploitation requires a non-browser WebSocket client and knowledge (or enumeration) of the view path and event names.\n\n### Patches\n\nFixed in **djust 1.0.4** (commit `1ae8aa9`, PR #1780). Both the auth-redirect and `on_mount`-hook-redirect branches of `handle_mount` now send the navigate frame **and then `close(code=4403)` and clear `self.view_instance`**, mirroring the existing `PermissionDenied` branch. Public / authorized mounts are unchanged. The same path is reachable via `handle_live_redirect_mount` (which delegates to `handle_mount`) and is covered by the same fix.\n\n1.0.4 also adds an opt-in defense-in-depth control, `LIVEVIEW_CONFIG['reauth_on_event'] = True` (default OFF), which re-resolves the user from the session and re-runs the view's auth check on **every** event for gated views.\n\n### Workarounds\n\nUpgrade to 1.0.4. If you cannot upgrade immediately, on affected versions ensure that **every `@event_handler` on a gated `LiveView` independently verifies the request user is authenticated and authorized** (e.g. check `request.user.is_authenticated` / permissions at the top of each handler), since the framework does not re-check after mount on `\u003c 1.0.4`. Alternatively, override the consumer's `handle_mount` to `await self.close(code=4403)` after emitting an auth redirect.\n\n### Proof of concept\n\nUsing Channels' `WebsocketCommunicator` against `LiveViewConsumer.as_asgi()` with an **anonymous** scope, mount a `login_required` view: the server emits a `navigate` frame but the socket stays open. Sending a subsequent `{\"type\":\"event\", \"handler\":\"\u003cmutating_handler\u003e\", ...}` frame reaches the handler and executes it without an authenticated session. On 1.0.4 the socket is closed with code `4403` immediately after the redirect and the event frame is rejected. (Regression test: `tests/test_ws_auth_close_socket.py`.)\n\n### Credits\n\nDiscovered internally during the djust v1.1.0 WebSocket-auth security review.","status":"published","published":"2026-08-25T16:06:31Z","modified":"2026-09-10T12:25:27.409576998Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high"}],"cwes":["CWE-285","CWE-306"],"updated_at":"2026-11-02T15:47:00.604718Z"},{"id":"PYSEC-2026-3829","title":"djust authentication bypass: a login_required / on_mount LiveView mount redirect does not close the WebSocket, allowing an unauthenticated client to dispatch event-handler calls","description":"### Impact\n\ndjust's `LiveViewConsumer` mounts a `LiveView` over a WebSocket. When a view is gated (`login_required` / `permission_required`, or an `on_mount` hook that returns a redirect) and the connecting user is not authorized, the consumer sent the client a `{\"type\":\"navigate\",\"to\":...}` redirect frame and then `return`ed — **without closing the socket and without clearing `self.view_instance`**. Only the `PermissionDenied` branch closed the connection (`close(4403)`).\n\nA real browser obeys the navigate frame and leaves, hiding the problem. A **raw WebSocket client that ignores the redirect** keeps an open, mounted socket. Because `handle_event` did not re-check authentication/authorization after mount, that client could then send `{\"type\":\"event\", ...}` frames and invoke any `@event_handler` method on the gated view **with no authenticated session** — an authentication bypass on the live mutation path.\n\n**Who is affected:** apps that expose `LiveView`s gated by `login_required` / `permission_required` / a redirecting `on_mount` hook, where the gated view's event handlers perform sensitive reads or mutations and do not independently re-verify the user. Exploitation requires a non-browser WebSocket client and knowledge (or enumeration) of the view path and event names.\n\n### Patches\n\nFixed in **djust 1.0.4** (commit `1ae8aa9`, PR #1780). Both the auth-redirect and `on_mount`-hook-redirect branches of `handle_mount` now send the navigate frame **and then `close(code=4403)` and clear `self.view_instance`**, mirroring the existing `PermissionDenied` branch. Public / authorized mounts are unchanged. The same path is reachable via `handle_live_redirect_mount` (which delegates to `handle_mount`) and is covered by the same fix.\n\n1.0.4 also adds an opt-in defense-in-depth control, `LIVEVIEW_CONFIG['reauth_on_event'] = True` (default OFF), which re-resolves the user from the session and re-runs the view's auth check on **every** event for gated views.\n\n### Workarounds\n\nUpgrade to 1.0.4. If you cannot upgrade immediately, on affected versions ensure that **every `@event_handler` on a gated `LiveView` independently verifies the request user is authenticated and authorized** (e.g. check `request.user.is_authenticated` / permissions at the top of each handler), since the framework does not re-check after mount on `\u003c 1.0.4`. Alternatively, override the consumer's `handle_mount` to `await self.close(code=4403)` after emitting an auth redirect.\n\n### Proof of concept\n\nUsing Channels' `WebsocketCommunicator` against `LiveViewConsumer.as_asgi()` with an **anonymous** scope, mount a `login_required` view: the server emits a `navigate` frame but the socket stays open. Sending a subsequent `{\"type\":\"event\", \"handler\":\"\u003cmutating_handler\u003e\", ...}` frame reaches the handler and executes it without an authenticated session. On 1.0.4 the socket is closed with code `4403` immediately after the redirect and the event frame is rejected. (Regression test: `tests/test_ws_auth_close_socket.py`.)\n\n### Credits\n\nDiscovered internally during the djust v1.1.0 WebSocket-auth security review.","status":"published","published":"2026-09-10T09:44:56.209696Z","modified":"2026-09-10T12:15:05.059650984Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high"}],"updated_at":"2026-11-02T15:52:57.255153Z"}]}}
