mirror of
https://github.com/calibrain/shelfmark.git
synced 2026-11-10 12:28:27 +00:00
Code scanning alert 106 (stack trace exposure on the release search 503) turned out to be worth a look. Jackett sends its API key as `?apikey=` in the query string, and when Jackett is unreachable the source builds its "unavailable" message from the requests exception, whose text includes the full request URL. `/api/releases` returns that message to whoever ran the search, so any signed-in user could read the Jackett key while Jackett was down. I reproduced it with Jackett pointed at a closed port: the 503 body had `apikey=<the key>` in it. Jackett was added in #1521 and isn't in a release yet, so nothing shipped with this. `SourceUnavailableError` now masks credentials in its message with the same `redact_secrets` the log formatter uses (query parameters like `apikey=`, `user:pass@` in URLs and so on). I did it in the exception rather than at the two Jackett sites that build the text, since its message is written for the user and any other source that ends up with a key in a URL would hit the same thing. The rest of the message stays readable, for example "Max retries exceeded with url: ...?apikey=(removed)&t=book". Prowlarr and slskd send their keys in headers so they didn't leak a key, but their messages do include the internal host and port. I left that alone here. Tests: two Jackett ones (a connection error on the search and on the indexer lookup, with the key in the exception text) and three on the exception itself. The four that check masking fail on current main. The full suite, ruff and basedpyright are clean.