Skip to content

Security Model

iderex edited this page Jul 11, 2026 · 16 revisions

Security Model

This plugin is the login path for your Jellyfin server, so it is built to fail closed: anything the plugin cannot positively verify is rejected, never waved through. This page describes the protections implemented today; it grows as the hardening program continues.

Identity binding (anti account-takeover)

An SSO login is bound to the identity provider's stable identifier — OpenID sub / SAML NameID — recorded as a canonical link. A first login whose name merely matches a pre-existing, unlinked Jellyfin account is refused (HTTP 403), not silently adopted, unless an administrator explicitly enables AllowExistingAccountLink for that provider. This prevents a user whose provider-supplied name equals an existing account (e.g. admin) from taking that account over.

SAML response validation (fail-closed)

A SAML response is accepted only when all of the following hold; any failure rejects the login:

  • Signature — exactly one signature, whose reference covers the element that is actually consumed (root Response or the single Assertion). This blocks XML-signature-wrapping ("verify one node, read another").
  • Time boundsNotOnOrAfter (and NotBefore when present) are enforced with a bounded clock skew. A missing or unparseable bound is rejected (it is not treated as "valid forever").
  • Audience — the assertion's AudienceRestriction must name this service provider (configurable; opt-out available for providers that cannot emit it). This stops an assertion minted for a different service from being replayed here.
  • One-time use — a consumed assertion ID cannot mint a second session within its validity window (per-provider replay cache).

Server-side request forgery (avatar fetch)

When avatar sync is configured, the URL is derived from identity-provider claims, so the fetch is constrained to public http(s) targets: the resolved address is validated at connect time (each redirect hop too), blocking loopback/private/link-local/CGNAT/ metadata ranges and DNS rebinding, and the download is bounded in time and size.

Concurrency

The in-flight OpenID authorize-state store is safe under concurrent logins, so parallel sign-ins cannot corrupt it or throw.

Reporting

Report vulnerabilities privately via Report a vulnerability. Security-relevant behavior is covered by the automated test suite, and login-path changes go through an adversarial security review before merge.

Clone this wiki locally