Vellum/internal/jellyfin
mithral 6e04e957b8 Rate limit every surface that checks a password
The limiter covered only /api/v1/auth/login. Jellyfin's AuthenticateByName
and Subsonic's authenticate both called auth.Authenticate with no limiting,
so an attacker brute-forced through those instead: the same password, the
same argon2, no ceiling.

The limiter moves from auth.Handlers onto *Authenticator, which all three
surfaces already hold, so they share one budget and splitting guesses
across surfaces gains nothing. main.go builds one authenticator and hands
it to both compat layers, so the sharing is real rather than intended.

Subsonic needs care: it has no login step, authenticate runs on every
request, so a naive check would charge playback against the login budget
and lock a listener out mid-album. The limiter is consulted only when a
credential was actually supplied, and a success or an uncredentialed
request spends nothing.

Verified red-green on all three: removing the Jellyfin gate fails
TestAuthenticateByNameIsRateLimited with 401 instead of 429; removing the
Subsonic credential guard fails
TestSuccessAndUncredentialedDoNotConsumeTheBudget; neutering AllowLogin or
ResetLogin fails the auth tests.

Known gap, unchanged: the limiter is in-process, so it resets on restart
and does not span replicas. Fine for one binary against one SQLite file.
2026-10-12 00:57:56 -04:00
..
dto Close the Jellyfin test gap 2026-10-11 16:10:58 -04:00
auth.go Waves 9-10: Jellyfin and Subsonic clients can browse and play 2026-10-11 15:05:43 -04:00
items.go Phase 2: split the fat packages along real boundaries 2026-10-11 16:03:10 -04:00
jellyfin.go Waves 9-10: Jellyfin and Subsonic clients can browse and play 2026-10-11 15:05:43 -04:00
jellyfin_test.go Rate limit every surface that checks a password 2026-10-12 00:57:56 -04:00
playback.go Phase 2: split the fat packages along real boundaries 2026-10-11 16:03:10 -04:00
query.go Phase 2: split the fat packages along real boundaries 2026-10-11 16:03:10 -04:00
sessions.go Phase 2: split the fat packages along real boundaries 2026-10-11 16:03:10 -04:00
system.go Rate limit every surface that checks a password 2026-10-12 00:57:56 -04:00