v1.7.0
Security release. The dashboard API now requires authentication, and it no longer hands out
the API key. If you run iplayer-arr, upgrade.
GET /api/config used to return the api_key in cleartext to any caller, and no /api/*
route required a credential. That key is the same secret protecting the Newznab and SABnzbd
endpoints, so anyone who could reach the port could read it and then drive the indexer and
download client as an authenticated peer.
After upgrading:
- Read your key with
docker exec <container> cat /config/api_key, or set your own value
with the newAPI_KEYenvironment variable and restart. - Open the dashboard. The setup wizard asks for the key once and stores it in the browser.
- Sonarr and Radarr need no changes. They authenticate by query parameter as before.
Reported responsibly by @archnexus707, who identified that the key disclosure collapsed the
whole authentication model rather than merely exposing a dashboard. Thank you.
- Every
/api/*route authenticates. The only exceptions are a liveness probe at
GET /api/healthzand the not-found catch-all, each with a written justification in code. api_keyremoved from theGET /api/configresponse.- The key is delivered out of band: an
API_KEYenvironment variable, or a file written at
mode 0600 in the config directory on every start, created atomically. - Constant time key comparison across the dashboard, Newznab and SABnzbd surfaces, which now
all fail closed on an unreadable or empty key. - A regression test derives the route list from the router itself and fails if any route is
registered without authentication and without an allowlisted justification. A second test
prevents routes being registered outside that registry. - New
BIND_ADDRvariable so the listener can be confined to loopback. - An episode grabbed before BBC published its playlist no longer sticks as permanently
failed. The history lookup ignored status, so once the retries ran out every later attempt
at the same episode was handed the dead entry and nothing was queued again, even after the
episode went live. Only a not-yet-available failure is superseded; every other terminal
failure still deduplicates, so a truncated or expired entry is not re-downloaded. (#52) - Bulk grabs claim in episode order. Downloads were read back in the byte order of their
random internal ids, which produced a stable scramble that looked shuffled and was
identical on every poll. Episode identity is now parsed from the release title at enqueue.
Reordering the queue by hand in the UI is not in this release and #51 stays open for it. - Release notes are built from the tag annotation again, and the CI diag suite no longer
picks a random host port that could collide. /api/searchreports anAvailabilityfield per result, so a client driving the API can
tell that an episode is listed but not yet published. The signal is best effort: it reuses
a cached quality lookup that the indexer feed populates for episodes it never checked, so
treatnot_yet_availableas reliable andavailableas a strong hint.