A 1.0 patch release that includes security fixes; upgrading from 1.0.8 is recommended. The 1.0 line is no longer maintained, so moving to 1.2 or later is advised.
Security
- The signed
state_snapshottoken no longer carries the raw session key. The token is signed, not encrypted, and the client stores it, so the session key was readable from the page. The envelope now holds a keyed digest of the session key (the same change as in 1.1 and later). Tokens issued before the upgrade no longer verify: the view falls back to one normalmount()and issues a new token. reauth_on_eventre-check now fails closed. WithLIVEVIEW_CONFIG["reauth_on_event"]on,LiveViewConsumer.handle_eventcaught any exception from the per-event authorization re-check (Http404orDoesNotExistout ofcheck_permissions, a failing session or auth backend), logged it at DEBUG and ran the event, so a user whose access had been revoked could still dispatch. The re-check now lives inLiveViewConsumer._reauth_recheckand denies on any exception: one WARNING naming only the exception type and view class (never the message or a traceback), navigate-to-login and close 4403 (both best effort, so a dead peer cannot turn the denial into an allow), and the handler does not run. Clean pass/fail results and the default-off behaviour are unchanged. Affects 1.0.4 through 1.0.8. Tests inpython/djust/tests/test_reauth_fail_closed.py.reauth_on_eventnow also covers frames the server sends on its own. WithLIVEVIEW_CONFIG["reauth_on_event"]on, a WebSocket whose user was logged out or lost a permission was refused on its next client event but kept receivingserver_push/push_to_view,db_notify,tick, presence andstart_asyncresult frames for a view withlogin_requiredorpermission_required. Each such turn now runs the same fresh-principal check as an event, under the render lock and before the hook runs; on failure the socket gets navigate-to-login and close 4403 and nothing is rendered or sent. A passed check covers the socket forLIVEVIEW_CONFIG["reauth_server_turn_interval"]seconds (default 5; 0 re-checks every turn), so ticking views do not read the session store on every tick. A check that raises denies and logs only the exception type and view class at WARNING. Off by default; behaviour withreauth_on_eventoff is unchanged. Tests inpython/djust/tests/test_server_turn_reauth.py.- Debug panel and
client-dev.jsnow escape interpolated values. The in-browser debug panel (loaded only whensettings.DEBUGis true) built its Events, Network, Patches, Components, Handlers, Variables and Warnings tabs, the element badge, and the hot-reload error toast as HTML strings without escaping, so text from application data (for example another user's input in a shared view) was parsed as markup in the developer's browser. Every interpolated value is now escaped (including attribute positions, via a quote-escapingescapeHtml), warningdocs_urllinks are limited to http(s)/relative URLs, and the toast usestextContent. The generateddebug-panel.js/debug-panel.min.jsbundles (and their.gz/.br/.mapsiblings) are rebuilt withscripts/build-client.sh. Production pages (DEBUG = False) never load the panel and were not affected. Tests intests/js/debug_panel_xss_escape.test.js.
Fixed
- Saved view state and the signed
state_snapshottoken of aTenantMixinview are bound to the tenant (#3328). The state backend entry, the Django-session entry (liveview_<path>and its__private,_componentsand__sticky__siblings) and the back-navigation token are keyed bytenant:<id>, so one session that reaches two tenants on the same URL keeps separate state and a mount under another tenant mounts fresh. A tenant view with no resolved tenant saves, restores and mints nothing. Thetenantcontext key is render-only, so a restoredself.tenantis no longer a serialized string. Views withoutTenantMixinare unchanged. State and tokens that tenant views saved before the upgrade are not found once (one fresh mount). V004no longer false-fires on framework-invoked lifecycle hooks (#1684). TheV004system check ("public method looks like an event handler but is missing@event_handler") flagged user overrides of hooks the framework calls directly (self.X()/getattr/hasattr) rather than through the user-event router — these must NOT carry@event_handler, but their names match the event-handler-like regex and were absent from theV004lifecycle-skip set inchecks/components.py. Canonical symptom:handle_presence_leave(bitdjust-org/djust-start#5). Added the 8 framework-invoked hooks (handle_presence_join/handle_presence_leave/handle_cursor_move/handle_tick/handle_async_result/handle_component_event/handle_info/on_wizard_complete) to the skip set. The fix originally landed on the1.1branch (#1685) against the pre-#1822-splitchecks.py; it was never ported tomain's splitchecks/(so the false-positive was live through 1.0.8) — this lands it onmain. New regressionTestV004LifecycleMethods::test_v004_ignores_framework_invoked_hooks_1684(gate-off verified, #1468).