v2.4.0
v2.4.0
Security hardening, per-role enrollment policy, breach-password check, and a "Where am I signed in?" sessions panel.
Security (10 fixes from internal review)
- Email enumeration on 2FA endpoints is now rate-limited (H1, M2).
- Atomic challenge consumption closes a passkey replay window (M1).
- Auth-path check hoisted before request-body buffering (M3).
- Audit-log labels are sanitized (no control chars, no
:separator confusion, 32-char cap) (L5). - Passkey assertion responses get the same rate limit as TOTP (L4).
- Plus L1, L2, L3, L6, L7 hardening across the controller and middleware.
Per-role 2FA policy
The old "Require 2FA for all users" toggle is replaced by an EnforcementScope setting:
- Optional — users opt in from the Setup page (default).
- Admins only — only Jellyfin admins must enroll. Recommended pattern for shared media servers.
- All users — everyone must enroll.
HIBP breach-password check (opt-in)
On sign-in, the first 5 hex chars of SHA-1(password) are sent to api.pwnedpasswords.com (k-anonymity — your password never leaves the server). A breach hit writes an audit entry and a warning log but never blocks sign-in. Fails open on outage. Off by default.
"Where am I signed in?" sessions panel
The Setup page now lists every device with a live access token for your account (stable data from IDeviceManager, not the transient session list). One-click self-revoke for any of them.
Upgrade
In-place upgrade. No migration steps; no config changes required.
Package checksum
- MD5:
EDE9E10A2658C8EBD8AEB002D19F1355 - SHA256:
0E622FA0D74B87B7DD39B668D9D8C51C4CC5661E89EFB5A79209E7C057ABD8A8
Sigstore-signed zip — verify with cosign verify-blob.