Skip to content

fix(security): redact sensitive URL parameters in logs#853

Merged
s0up4200 merged 7 commits intodevelopfrom
fix/redact-secrets-in-logs
Jan 2, 2026
Merged

fix(security): redact sensitive URL parameters in logs#853
s0up4200 merged 7 commits intodevelopfrom
fix/redact-secrets-in-logs

Conversation

@s0up4200
Copy link
Collaborator

@s0up4200 s0up4200 commented Dec 24, 2025

Summary

  • Add pkg/redact package to centralize redaction of sensitive query parameters (apikey, api_key, passkey, token, password) from URLs and error messages
  • Handle userinfo passwords (user:pass@hostuser:REDACTED@host) and proxy path segments (/proxy/{key}//proxy/REDACTED/)
  • Apply redaction to all identified leak points across the codebase

Fixes #839

Summary by CodeRabbit

  • New Features

    • Application-wide redaction now masks API keys, tokens, passwords, sensitive URL query params, proxy path keys, and credential details in logs and error messages to prevent leaking secrets.
    • Access and request logs no longer expose raw paths or credential values.
  • Tests

    • New unit and integration tests verify redaction for URLs, query parameters, proxy paths, basic auth strings, and wrapped error messages.

✏️ Tip: You can customize this high-level summary in your review settings.

Add pkg/redact package to centralize redaction of sensitive query
parameters (apikey, api_key, passkey, token, password) from URLs
and error messages. Also handles userinfo passwords and proxy path
segments containing API keys.

Apply redaction to all identified leak points:
- pkg/gojackett: HTTP errors and enclosure URLs
- pkg/prowlarr: request errors
- internal/services/jackett: fetchCaps, Download, service logs
- internal/api/handlers: jackett discovery, torrent URLs
- internal/proxy: middleware, handler, retry transport
- internal/metrics: basic auth credentials

Fixes #839
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 24, 2025

Warning

Rate limit exceeded

@s0up4200 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 11 minutes and 12 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between d5454f0 and 1abe8a5.

📒 Files selected for processing (2)
  • internal/proxy/retry_transport.go
  • internal/services/jackett/service.go

Walkthrough

Adds a new pkg/redact package and integrates redaction across logging and error wrapping in handlers, proxy, metrics, services, and clients to prevent leaking sensitive URL/query/basic-auth data; includes unit tests and a regression test.

Changes

Cohort / File(s) Summary
New redact package
pkg/redact/redact.go, pkg/redact/redact_test.go, pkg/redact/url_error_test.go
New utilities: URLString, URLError, String, ProxyPath, BasicAuthUser and tests to sanitize URLs, query params (apikey, api_key, passkey, token, password), userinfo and proxy paths.
API handlers
internal/api/handlers/jackett.go, internal/api/handlers/torrents.go
Replace raw URL/error logs with redact.URLString / redact.String to avoid leaking URLs and query params in error output.
Proxy & middleware
internal/proxy/handler.go, internal/proxy/middleware.go, internal/proxy/retry_transport.go
Use redacted path/URL/error values in logs; remove some detailed path/context logging; middleware now returns immediately on missing API key; retry_transport refactors retryability checks and logs redacted URL/error content.
Metrics & server
internal/metrics/server.go
Redacts basic-auth credential display via redact.BasicAuthUser in invalid-auth logging.
Jackett service & client
internal/services/jackett/client.go, internal/services/jackett/service.go, internal/services/jackett/client_test.go
Wrap HTTP errors with redact.URLError, log base URLs with redact.URLString, and add regression test TestDiscoverJackettIndexers_RedactsAPIKey.
Third-party clients / gojackett / prowlarr
pkg/gojackett/http.go, pkg/gojackett/methods.go, pkg/prowlarr/client.go
Redact request URLs and wrap HTTP errors with redact.URLError; use redact.URLString in retry/on-retry logging.
Logging context adjustments
internal/api/middleware/logger.go, internal/proxy/handler.go, internal/proxy/middleware.go
Replace raw request path with redact.ProxyPath in access logs and shorten/omit detailed sensitive fields from logger context.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I nibble logs and hide each key,

REDACTED whispers where secrets used to be,
No more traces in the stream,
Quiet logs and tidy dream,
Hop, redact, and rest with me.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.22% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding redaction for sensitive URL parameters in logs across the codebase to fix the security issue.
Linked Issues check ✅ Passed The PR comprehensively addresses issue #839 by implementing redaction of sensitive query parameters (apikey, api_key, token, passkey, password), userinfo passwords, and proxy paths throughout the codebase.
Out of Scope Changes check ✅ Passed All changes are directly related to redacting sensitive data in logs and errors. The new redact package and its application across handlers, services, and middleware are all in-scope for fixing the secret leakage issue.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
pkg/redact/redact.go (2)

14-23: Redaction primitives are well-scoped; consider small proxy-path regex enhancement

URL/userinfo/query redaction in URLString, plus the layered String/ProxyPath helpers, covers the sensitive cases (apikey/api_key/passkey/token/password, userinfo passwords, /proxy/{key}/ segments) without overreaching. The fallback from URLString to String on parse failure is a good safety net.

One minor, optional improvement: proxyPathRegex ((/proxy/)([^/]+)(/|$)) will not match /proxy/<key>?... when applied to arbitrary strings (because ? prevents the final (/|$) from matching). It’s already correct for real URLs via URLString (which passes only the path), but if you expect to feed full raw request lines or log messages into String, you might want to extend the terminator to [/?#] to also catch query/fragment cases.

Also applies to: 28-78, 101-118, 120-127, 129-140


80-99: URLError redacts correctly but may drop outer error context when misused

URLError correctly finds a *url.Error and replaces its URL with URLString(urlErr.URL), which fixes the core leak for http.Client failures. Note that it returns a new url.Error, discarding any outer wrappers that may have been added around the original error. That’s fine for current call sites that pass the raw Do error, but if you later call URLError on already-wrapped errors you’ll lose that higher-level context.

To avoid surprises, either (a) document that callers should pass the raw transport error, or (b) consider mutating urlErr.URL in place and returning the original err so any outer wrapping is preserved.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ace0101 and c5fb29e.

📒 Files selected for processing (15)
  • internal/api/handlers/jackett.go
  • internal/api/handlers/torrents.go
  • internal/metrics/server.go
  • internal/proxy/handler.go
  • internal/proxy/middleware.go
  • internal/proxy/retry_transport.go
  • internal/services/jackett/client.go
  • internal/services/jackett/client_test.go
  • internal/services/jackett/service.go
  • pkg/gojackett/http.go
  • pkg/gojackett/methods.go
  • pkg/prowlarr/client.go
  • pkg/redact/redact.go
  • pkg/redact/redact_test.go
  • pkg/redact/url_error_test.go
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-11-06T12:11:04.963Z
Learnt from: Audionut
Repo: autobrr/qui PR: 553
File: internal/services/crossseed/service.go:1045-1082
Timestamp: 2025-11-06T12:11:04.963Z
Learning: The autobrr/qui project uses a custom go-qbittorrent client library (github.com/autobrr/go-qbittorrent) that supports both "paused" and "stopped" parameters when adding torrents via the options map. Both parameters should be set together when controlling torrent start state, as seen in internal/services/crossseed/service.go and throughout the codebase.

Applied to files:

  • internal/services/jackett/client.go
  • internal/api/handlers/torrents.go
📚 Learning: 2025-11-25T22:46:03.762Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 632
File: internal/backups/service.go:1401-1404
Timestamp: 2025-11-25T22:46:03.762Z
Learning: In qui's backup service (internal/backups/service.go), background torrent downloads initiated during manifest import intentionally use a fire-and-forget pattern with the shared service context (s.ctx). Per-run cancellation is not needed, as orphaned downloads completing after run deletion are considered harmless and acceptable. This design prioritizes simplicity over per-run lifecycle management for background downloads.

Applied to files:

  • internal/services/jackett/client.go
  • internal/api/handlers/torrents.go
📚 Learning: 2025-11-27T15:33:39.007Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 641
File: internal/services/jackett/service.go:309-330
Timestamp: 2025-11-27T15:33:39.007Z
Learning: In internal/services/jackett/service.go, synchronous execution paths (test executors, interactive searches with explicit indexer selection, and scheduler-unavailable fallback) intentionally pass jobID=0 to result callbacks. This is acceptable because outcome tracking via ReportIndexerOutcome is only used for async cross-seed operations that always use the scheduler and receive unique jobIDs. Interactive searches and tests do not use outcome tracking.

Applied to files:

  • internal/api/handlers/jackett.go
  • internal/services/jackett/client_test.go
📚 Learning: 2025-12-11T08:40:01.329Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 746
File: internal/services/reannounce/service.go:480-481
Timestamp: 2025-12-11T08:40:01.329Z
Learning: In autobrr/qui's internal/services/reannounce/service.go, the hasHealthyTracker, getProblematicTrackers, and getHealthyTrackers functions intentionally match qbrr's lenient tracker health logic (skip unregistered trackers and check if any other tracker is healthy) rather than go-qbittorrent's strict isTrackerStatusOK logic (which treats unregistered as an immediate failure). For multi-tracker torrents, if one tracker is working, reannouncing won't help. The duplication of the health check logic across these three functions is acceptable as it's a simple one-liner, and extracting it would add unnecessary complexity.

Applied to files:

  • internal/proxy/handler.go
  • internal/api/handlers/torrents.go
🧬 Code graph analysis (8)
pkg/prowlarr/client.go (1)
pkg/redact/redact.go (1)
  • URLError (83-99)
pkg/gojackett/http.go (1)
pkg/redact/redact.go (3)
  • URLError (83-99)
  • URLString (28-78)
  • String (107-118)
internal/services/jackett/client.go (1)
pkg/redact/redact.go (2)
  • URLError (83-99)
  • URLString (28-78)
internal/services/jackett/service.go (1)
pkg/redact/redact.go (1)
  • URLString (28-78)
internal/proxy/handler.go (1)
pkg/redact/redact.go (1)
  • String (107-118)
internal/services/jackett/client_test.go (1)
internal/services/jackett/client.go (1)
  • DiscoverJackettIndexers (481-565)
internal/metrics/server.go (1)
pkg/redact/redact.go (1)
  • BasicAuthUser (131-140)
internal/api/handlers/torrents.go (1)
pkg/redact/redact.go (1)
  • URLString (28-78)
🔇 Additional comments (23)
internal/services/jackett/client_test.go (1)

7-16: Regression test for API-key redaction looks solid

The new imports and TestDiscoverJackettIndexers_RedactsAPIKey cleanly exercise the failure path without depending on a specific error shape, while asserting both absence of the raw key and presence of apikey=REDACTED when applicable. No issues found.

Also applies to: 143-175

pkg/prowlarr/client.go (1)

17-19: SearchIndexer error wrapping now safely redacts request URLs

Wrapping c.httpClient.Do errors with redact.URLError(err) inside fmt.Errorf("prowlarr request failed: %w", …) achieves URL redaction for *url.Error without changing the surrounding message or control flow. This is aligned with the PR’s objectives and looks correct.

Also applies to: 149-152

internal/services/jackett/service.go (1)

26-31: Redacting base_url in search logs is appropriate and non-invasive

Using redact.URLString(idx.BaseURL) for the base_url log field keeps the existing observability while ensuring any misconfigured base URLs with query secrets or userinfo are masked. No functional behavior changes; this is a safe hardening step.

Also applies to: 1785-1810

internal/api/handlers/jackett.go (1)

19-22: Discovery error logging now properly redacts base URL and error message

The DiscoverIndexers handler’s error path now logs base_url via redact.URLString and the error text via redact.String(err.Error()), which should block the Prowlarr API-key leak that motivated issue #839 without altering response codes or bodies. This looks correct and consistent with the new redact utilities.

Also applies to: 840-865

internal/api/handlers/torrents.go (1)

25-29: URL logging in AddTorrent is now redaction-aware

Switching the three error logs in AddTorrent to use redact.URLString(url) ensures that any sensitive query parameters or userinfo embedded in magnet/HTTP URLs are masked before hitting logs, while keeping the rest of the context intact. No control-flow changes; this is a straightforward hardening.

Also applies to: 553-599

internal/metrics/server.go (1)

12-18: Invalid metrics basic-auth credentials are now logged without passwords

Using redact.BasicAuthUser(cred) in the warning for malformed basicAuthUsersConfig avoids exposing raw user:password pairs in logs while still indicating which entry was bad. This is a good, low-risk improvement.

Also applies to: 32-41

pkg/gojackett/methods.go (1)

13-16: GetEnclosureCtx now wraps errors with a redacted enclosure string

Changing the errors.Wrap context from the raw enclosure to redact.URLString(enclosure) preserves the usefulness of the error message while masking any sensitive data in the enclosure URL. Control flow and return types are unchanged.

Also applies to: 86-90

internal/proxy/handler.go (1)

264-269: LGTM! Appropriate redaction of proxy errors.

The change correctly applies redaction to error messages that may contain sensitive URL parameters while preserving all relevant context (client, instanceId, method) for debugging.

pkg/redact/url_error_test.go (2)

14-117: LGTM! Comprehensive test coverage for URLError redaction.

The test cases cover all critical scenarios including nil errors, various sensitive parameters (apikey, token, password, api_key, passkey), multiple params, wrapped errors, and non-url.Error cases. The assertions properly verify both the presence of REDACTED markers and the absence of actual secrets.


119-140: LGTM! Important validation of error type preservation.

This test ensures that URLError() maintains the url.Error type for errors.As() compatibility, which is crucial for error handling code that checks error types. The verification that the Op field is preserved and the URL is redacted is thorough.

internal/proxy/retry_transport.go (3)

52-59: LGTM! Proper redaction on successful retry.

The URL redaction here ensures that even successful retry logs don't expose sensitive query parameters or credentials.


66-71: LGTM! Comprehensive redaction for non-retryable errors.

Both the error message and URL are redacted, providing defense-in-depth since errors often contain the request URL with sensitive parameters.


80-108: LGTM! Consistent redaction across all retry paths.

The redaction is applied uniformly across all logging scenarios: non-idempotent methods, max retries exceeded, and retry attempts. This consistency ensures no log path accidentally leaks sensitive data.

pkg/gojackett/http.go (2)

30-36: LGTM! Proper error redaction in HTTP client.

The dual redaction approach (both the error via URLError and the URL parameter via URLString) ensures comprehensive protection against secret leakage in HTTP errors.


111-132: LGTM! Retry logic properly redacts sensitive data.

The redaction is correctly applied to both the returned error and the retry logging callback, ensuring that the full retry sequence doesn't leak secrets while maintaining debuggability.

internal/services/jackett/client.go (2)

254-262: LGTM! Consistent redaction across all caps fetch paths.

The redaction is uniformly applied to all three backend types (Jackett, Prowlarr, Native), ensuring that caps fetch errors don't leak API keys regardless of the backend configuration.

Also applies to: 289-297, 324-332


366-374: LGTM! Download errors properly redacted.

Both network errors and HTTP status errors are appropriately redacted. The DownloadError struct stores the redacted URL, ensuring that any subsequent error handling or logging won't accidentally leak the original URL with sensitive parameters.

internal/proxy/middleware.go (2)

112-114: LGTM! Appropriate reduction of logged API key details.

Logging only whether the key exists (rather than the key itself or portions of it) is the right approach for security. This still provides debugging capability to identify missing keys without exposing sensitive data.


116-122: Good catch! Return statement prevents unauthorized access.

The addition of the return statement after the "Missing API key" error response is critical. Without it, execution would continue to next.ServeHTTP(w, r.WithContext(ctx)) at line 162, potentially allowing unauthenticated requests to proceed. This is an important security fix.

pkg/redact/redact_test.go (4)

11-145: LGTM! Excellent test coverage for URLString.

The tests comprehensively cover:

  • All sensitive parameter types (apikey, api_key, passkey, token, password)
  • Case-insensitive matching (critical for security)
  • Edge cases (empty strings, empty param values, multi-valued params)
  • Combined scenarios (userinfo + query params, proxy paths)
  • Non-sensitive parameters (ensuring they're preserved)

This thorough coverage helps ensure no regression in the redaction logic.


147-245: LGTM! Comprehensive testing of string-based redaction.

The test cases cover important real-world scenarios including:

  • Error messages containing sensitive data
  • Unparseable URL fragments (ensuring fallback to regex works)
  • Multiple parameters in a single string
  • Combination scenarios (userinfo, proxy paths)

The coverage ensures that even malformed or partial URLs in error messages don't leak secrets.


247-287: LGTM! Focused proxy path redaction tests.

The test cases appropriately cover the proxy path redaction scenarios including edge cases like trailing slashes and keys at the end of paths. The exact-match assertions are appropriate for this specific use case.


289-329: LGTM! Complete basic auth redaction tests.

The test cases cover all relevant scenarios for basic authentication credential redaction, including edge cases like empty passwords and complex password characters. The tests ensure usernames are preserved while passwords are consistently redacted.

- Split isRetryableError into smaller helper functions to reduce
  cognitive complexity
- Rename max parameter to maxBackoff to avoid shadowing builtin
- Use range over int (Go 1.22+) for backoff calculation loop
- Remove deprecated netErr.Temporary() call
- Add nolint:wrapcheck directive for RoundTrip (transport errors
  should not be wrapped)
- Use testify assertions in redact package tests
@s0up4200 s0up4200 added this to the v1.12.0 milestone Dec 24, 2025
@s0up4200 s0up4200 self-assigned this Dec 24, 2025
Apply redact.ProxyPath() to URL paths in logger middleware and
proxy handler to prevent API key leakage in regular debug logs.
The previous commit only covered error logs.
@s0up4200 s0up4200 changed the title fix(security): redact sensitive URL parameters in error logs fix(security): redact sensitive URL parameters in logs Dec 31, 2025
@s0up4200 s0up4200 changed the base branch from main to develop January 2, 2026 07:20
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
internal/api/middleware/logger.go (1)

46-46: Proxy path redaction correctly applied.

The change properly redacts proxy path patterns (e.g., /proxy/{key}//proxy/REDACTED/) in the access log.

Note that r.URL.Path contains only the path component, so query parameters (e.g., ?apikey=...) are not logged here. This is a safe approach that prevents any query parameter leaks in this middleware. If more comprehensive request logging is desired for debugging while maintaining security, consider using redact.URLString(r.URL.String()) to log the complete URL with all sensitive components redacted.

Optional: Log complete redacted URL for more comprehensive debugging

If logging the full request URL (including query parameters but redacted) would be valuable for debugging, consider:

-						"url":        redact.ProxyPath(r.URL.Path),
+						"url":        redact.URLString(r.URL.String()),

This would log the complete URL with query parameters like apikey, passkey, token, etc. automatically redacted, providing more debugging context while maintaining security.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 949a4a1 and d5454f0.

📒 Files selected for processing (2)
  • internal/api/middleware/logger.go
  • internal/proxy/handler.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/proxy/handler.go
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-28T18:44:10.496Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 876
File: internal/logstream/hub_test.go:188-192
Timestamp: 2025-12-28T18:44:10.496Z
Learning: In Go 1.25 (Aug 2025), use wg.Go(func()) to spawn a goroutine and automate the Add/Done lifecycle. Replace manual patterns like wg.Add(1); go func(){ defer wg.Done(); ... }() with wg.Go(func(){ ... }). Ensure the codebase builds with Go 1.25+ and apply this in relevant Go files (e.g., internal/logstream/hub_test.go). If targeting older Go versions, maintain the existing pattern.

Applied to files:

  • internal/api/middleware/logger.go
🧬 Code graph analysis (1)
internal/api/middleware/logger.go (1)
pkg/redact/redact.go (1)
  • ProxyPath (122-127)
🔇 Additional comments (1)
internal/api/middleware/logger.go (1)

13-14: LGTM!

The import is correctly added to support the redaction functionality used below.

@s0up4200 s0up4200 added the logger label Jan 2, 2026
@s0up4200 s0up4200 merged commit eb2bee0 into develop Jan 2, 2026
11 checks passed
@s0up4200 s0up4200 deleted the fix/redact-secrets-in-logs branch January 2, 2026 09:46
alexlebens pushed a commit to alexlebens/infrastructure that referenced this pull request Jan 4, 2026
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/autobrr/qui](https://github.com/autobrr/qui) | minor | `v1.11.0` → `v1.12.0` |

---

### Release Notes

<details>
<summary>autobrr/qui (ghcr.io/autobrr/qui)</summary>

### [`v1.12.0`](https://github.com/autobrr/qui/releases/tag/v1.12.0)

[Compare Source](autobrr/qui@v1.11.0...v1.12.0)

#### Changelog

##### New Features

- [`202e950`](autobrr/qui@202e950): feat(automations): Add `free_space` condition ([#&#8203;1061](autobrr/qui#1061)) ([@&#8203;Barcode-eng](https://github.com/Barcode-eng))
- [`3b106d6`](autobrr/qui@3b106d6): feat(automations): make conditions optional for non-delete rules and add drag reorder ([#&#8203;939](autobrr/qui#939)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`0684d75`](autobrr/qui@0684d75): feat(config): Add QUI\_\_OIDC\_CLIENT\_SECRET\_FILE env var ([#&#8203;841](autobrr/qui#841)) ([@&#8203;PedDavid](https://github.com/PedDavid))
- [`dac0173`](autobrr/qui@dac0173): feat(config): allow disabling tracker icon fetching ([#&#8203;823](autobrr/qui#823)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`dc10bad`](autobrr/qui@dc10bad): feat(crossseed): add cancel run and opt-in errored torrent recovery ([#&#8203;918](autobrr/qui#918)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`cd1fcc9`](autobrr/qui@cd1fcc9): feat(crossseed): add custom category option for cross-seeds ([#&#8203;907](autobrr/qui#907)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`d189fe9`](autobrr/qui@d189fe9): feat(crossseed): add indexerName to webhook apply + fix category mode defaults ([#&#8203;916](autobrr/qui#916)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`03a147e`](autobrr/qui@03a147e): feat(crossseed): add option to skip recheck-required matches ([#&#8203;825](autobrr/qui#825)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`edae00a`](autobrr/qui@edae00a): feat(crossseed): add optional hardlink mode for cross-seeding ([#&#8203;849](autobrr/qui#849)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`0938436`](autobrr/qui@0938436): feat(crossseed): add source aliasing for WEB/WEB-DL/WEBRip precheck matching ([#&#8203;874](autobrr/qui#874)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`65f6129`](autobrr/qui@65f6129): feat(crossseed): show failure reasons, prune runs, and add cache cleanup ([#&#8203;923](autobrr/qui#923)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e10fba8`](autobrr/qui@e10fba8): feat(details): torrent details panel improvements ([#&#8203;884](autobrr/qui#884)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`6921140`](autobrr/qui@6921140): feat(docs): add Docusaurus documentation site ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`6a5a66c`](autobrr/qui@6a5a66c): feat(docs): add Icon and webUI variables to the Unraid install guide ([#&#8203;942](autobrr/qui#942)) ([@&#8203;BaukeZwart](https://github.com/BaukeZwart))
- [`281fce7`](autobrr/qui@281fce7): feat(docs): add local search plugin ([#&#8203;1076](autobrr/qui#1076)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`566de08`](autobrr/qui@566de08): feat(docs): add qui logo, update readme, remove v4 flag ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`b83ac5a`](autobrr/qui@b83ac5a): feat(docs): apply minimal.css theme to Docusaurus ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`fe6a6df`](autobrr/qui@fe6a6df): feat(docs): improve documentation pages and add support page ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`62a7ad5`](autobrr/qui@62a7ad5): feat(docs): use qui favicon ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`5d124c0`](autobrr/qui@5d124c0): feat(orphan): add auto cleanup mode ([#&#8203;897](autobrr/qui#897)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`3172ad9`](autobrr/qui@3172ad9): feat(settings): add log settings + live log stream ([#&#8203;876](autobrr/qui#876)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`3c1b34b`](autobrr/qui@3c1b34b): feat(torrents): add "torrent introuvable" to unregistered status ([#&#8203;836](autobrr/qui#836)) ([@&#8203;kephasdev](https://github.com/kephasdev))
- [`afe4d39`](autobrr/qui@afe4d39): feat(torrents): add tracker URL editing for single torrents ([#&#8203;848](autobrr/qui#848)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`76dedd7`](autobrr/qui@76dedd7): feat(torrents): update GeneralTabHorizontal to display limits and improve layout ([#&#8203;1078](autobrr/qui#1078)) ([@&#8203;martylukyy](https://github.com/martylukyy))
- [`6831c24`](autobrr/qui@6831c24): feat(ui): unify payment options into single dialog ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`4dcdf7f`](autobrr/qui@4dcdf7f): feat(web): add local file access indicator to instance cards ([#&#8203;911](autobrr/qui#911)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`a560e5e`](autobrr/qui@a560e5e): feat(web): compact torrent details panel ([#&#8203;833](autobrr/qui#833)) ([@&#8203;martylukyy](https://github.com/martylukyy))
- [`557e7bd`](autobrr/qui@557e7bd): feat: add issue/discussion template ([#&#8203;945](autobrr/qui#945)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`8b93719`](autobrr/qui@8b93719): feat: add workflow automation system with category actions, orphan scanner, and hardlink detection ([#&#8203;818](autobrr/qui#818)) ([@&#8203;s0up4200](https://github.com/s0up4200))

##### Bug Fixes

- [`b85ad6b`](autobrr/qui@b85ad6b): fix(automations): allow delete rules to match incomplete torrents ([#&#8203;926](autobrr/qui#926)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`ae06200`](autobrr/qui@ae06200): fix(automations): make tags field condition operators tag-aware ([#&#8203;908](autobrr/qui#908)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`ace0101`](autobrr/qui@ace0101): fix(crossseed): detect folder mismatch for bare file to folder cross-seeds ([#&#8203;846](autobrr/qui#846)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`1cc1243`](autobrr/qui@1cc1243): fix(crossseed): enforce resolution and language matching with sensible defaults ([#&#8203;855](autobrr/qui#855)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`cefb9cd`](autobrr/qui@cefb9cd): fix(crossseed): execute external program reliably after injection ([#&#8203;1083](autobrr/qui#1083)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`867e2da`](autobrr/qui@867e2da): fix(crossseed): improve matching with size validation and relaxed audio checks ([#&#8203;845](autobrr/qui#845)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`4b5079b`](autobrr/qui@4b5079b): fix(crossseed): persist custom category settings in PATCH handler ([#&#8203;913](autobrr/qui#913)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`cfbbc1f`](autobrr/qui@cfbbc1f): fix(crossseed): prevent season packs matching episodes ([#&#8203;854](autobrr/qui#854)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`c7c1706`](autobrr/qui@c7c1706): fix(crossseed): reconcile interrupted runs on startup ([#&#8203;1084](autobrr/qui#1084)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`7d633bd`](autobrr/qui@7d633bd): fix(crossseed): use ContentPath for manually-managed single-file torrents ([#&#8203;832](autobrr/qui#832)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`d5db761`](autobrr/qui@d5db761): fix(database): include arr\_instances in string pool cleanup + remove auto-recovery ([#&#8203;898](autobrr/qui#898)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`c73ec6f`](autobrr/qui@c73ec6f): fix(database): prevent race between stmt cache access and db close ([#&#8203;840](autobrr/qui#840)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`a40b872`](autobrr/qui@a40b872): fix(db): drop legacy hardlink columns from cross\_seed\_settings ([#&#8203;912](autobrr/qui#912)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e400af3`](autobrr/qui@e400af3): fix(db): recover wedged SQLite writer + stop cross-seed tight loop ([#&#8203;890](autobrr/qui#890)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`90e15b4`](autobrr/qui@90e15b4): fix(deps): update rls to recognize IP as iPlayer ([#&#8203;922](autobrr/qui#922)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`8e81b9f`](autobrr/qui@8e81b9f): fix(proxy): honor TLSSkipVerify for proxied requests ([#&#8203;1051](autobrr/qui#1051)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`eb2bee0`](autobrr/qui@eb2bee0): fix(security): redact sensitive URL parameters in logs ([#&#8203;853](autobrr/qui#853)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`40982bc`](autobrr/qui@40982bc): fix(themes): prevent reset on license errors, improve switch performance ([#&#8203;844](autobrr/qui#844)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`a8a32f7`](autobrr/qui@a8a32f7): fix(ui): incomplete torrents aren't "Completed: 1969-12-31" ([#&#8203;851](autobrr/qui#851)) ([@&#8203;finevan](https://github.com/finevan))
- [`5908bba`](autobrr/qui@5908bba): fix(ui): preserve category collapse state when toggling incognito mode ([#&#8203;834](autobrr/qui#834)) ([@&#8203;jabloink](https://github.com/jabloink))
- [`25c847e`](autobrr/qui@25c847e): fix(ui): torrents with no creation metadata don't display 1969 ([#&#8203;873](autobrr/qui#873)) ([@&#8203;finevan](https://github.com/finevan))
- [`6403b6a`](autobrr/qui@6403b6a): fix(web): column filter status now matches all states in category ([#&#8203;880](autobrr/qui#880)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`eafc4e7`](autobrr/qui@eafc4e7): fix(web): make delete cross-seed check rely on content\_path matches ([#&#8203;1080](autobrr/qui#1080)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`d57c749`](autobrr/qui@d57c749): fix(web): only show selection checkbox on normal view ([#&#8203;830](autobrr/qui#830)) ([@&#8203;jabloink](https://github.com/jabloink))
- [`60338f6`](autobrr/qui@60338f6): fix(web): optimize TorrentDetailsPanel for mobile view and make tabs scrollable horizontally ([#&#8203;1066](autobrr/qui#1066)) ([@&#8203;martylukyy](https://github.com/martylukyy))
- [`aedab87`](autobrr/qui@aedab87): fix(web): speed limit input reformatting during typing ([#&#8203;881](autobrr/qui#881)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`df7f3e0`](autobrr/qui@df7f3e0): fix(web): truncate file progress percentage instead of rounding ([#&#8203;919](autobrr/qui#919)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`2fadd01`](autobrr/qui@2fadd01): fix(web): update eslint config for flat config compatibility ([#&#8203;879](autobrr/qui#879)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`721cedd`](autobrr/qui@721cedd): fix(web): use fixed heights for mobile torrent cards ([#&#8203;812](autobrr/qui#812)) ([@&#8203;jabloink](https://github.com/jabloink))
- [`a7db605`](autobrr/qui@a7db605): fix: remove pnpm-workspace.yaml breaking CI ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`c0ddc0a`](autobrr/qui@c0ddc0a): fix: use prefix matching for allowed bash commands ([@&#8203;s0up4200](https://github.com/s0up4200))

##### Other Changes

- [`fff52ce`](autobrr/qui@fff52ce): chore(ci): disable reviewer ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`7ef2a38`](autobrr/qui@7ef2a38): chore(ci): fix automated triage and deduplication workflows ([#&#8203;1057](autobrr/qui#1057)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`d84910b`](autobrr/qui@d84910b): chore(docs): move Tailwind to documentation workspace only ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`37ebe05`](autobrr/qui@37ebe05): chore(docs): move netlify.toml to documentation directory ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e25de38`](autobrr/qui@e25de38): chore(docs): remove disclaimer ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`c59b809`](autobrr/qui@c59b809): chore(docs): update support sections ([#&#8203;1063](autobrr/qui#1063)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`b723523`](autobrr/qui@b723523): chore(tests): remove dead tests and optimize slow test cases ([#&#8203;842](autobrr/qui#842)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`662a1c6`](autobrr/qui@662a1c6): chore(workflows): update runners from 4vcpu to 2vcpu for all jobs ([#&#8203;859](autobrr/qui#859)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`46f2a1c`](autobrr/qui@46f2a1c): chore: clean up repo root by moving Docker, scripts, and community docs ([#&#8203;1054](autobrr/qui#1054)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`2f27c0d`](autobrr/qui@2f27c0d): chore: remove old issue templates ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`04f361a`](autobrr/qui@04f361a): ci(triage): add labeling for feature-requests-ideas discussions ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`f249c69`](autobrr/qui@f249c69): ci(triage): remove needs-triage label after applying labels ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`bdda1de`](autobrr/qui@bdda1de): ci(workflows): add self-dispatch workaround for discussion events ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`a9732a2`](autobrr/qui@a9732a2): ci(workflows): increase max-turns to 25 for Claude workflows ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`d7d830d`](autobrr/qui@d7d830d): docs(README): add Buy Me a Coffee link ([#&#8203;863](autobrr/qui#863)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`266d92e`](autobrr/qui@266d92e): docs(readme): Clarify ignore pattern ([#&#8203;878](autobrr/qui#878)) ([@&#8203;quorn23](https://github.com/quorn23))
- [`9586084`](autobrr/qui@9586084): docs(readme): add banner linking to stable docs ([#&#8203;925](autobrr/qui#925)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e36a621`](autobrr/qui@e36a621): docs(readme): use markdown link for Polar URL ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`9394676`](autobrr/qui@9394676): docs: add frontmatter titles and descriptions, remove marketing language ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`ba9d45e`](autobrr/qui@ba9d45e): docs: add local filesystem access snippet and swizzle Details component ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`4329edd`](autobrr/qui@4329edd): docs: disclaimer about unreleased features ([#&#8203;943](autobrr/qui#943)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`735d065`](autobrr/qui@735d065): docs: improve external programs, orphan scan, reverse proxy, tracker icons documentation ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`78faef2`](autobrr/qui@78faef2): docs: remove premature tip and fix stat command ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`eaad3bf`](autobrr/qui@eaad3bf): docs: update social card image in Docusaurus configuration ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`02a68e5`](autobrr/qui@02a68e5): refactor(crossseed): hardcode ignore patterns for file matching ([#&#8203;915](autobrr/qui#915)) ([@&#8203;s0up4200](https://github.com/s0up4200))

**Full Changelog**: <autobrr/qui@v1.11.0...v1.12.0>

#### Docker images

- `docker pull ghcr.io/autobrr/qui:v1.12.0`
- `docker pull ghcr.io/autobrr/qui:latest`

#### What to do next?

- Join our [Discord server](https://discord.autobrr.com/qui)

Thank you for using qui!

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi42OS4yIiwidXBkYXRlZEluVmVyIjoiNDIuNjkuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiaW1hZ2UiXX0=-->

Reviewed-on: https://gitea.alexlebens.dev/alexlebens/infrastructure/pulls/3060
Co-authored-by: Renovate Bot <renovate-bot@alexlebens.net>
Co-committed-by: Renovate Bot <renovate-bot@alexlebens.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Torznab indexers error logs can leak secrets

1 participant