> ## Documentation Index
> Fetch the complete documentation index at: https://docs.questarr.app/llms.txt
> Use this file to discover all available pages before exploring further.

# DEPENDENCIES

# Dependency Management

This document describes how Questarr selects, obtains, and tracks its dependencies.

## Selection

Dependencies are added deliberately as part of normal development, via `npm install`, and land in `package.json` alongside the feature or fix that needs them. Preference is given to actively maintained, widely used packages already common in the Node/React ecosystem. New dependencies go through the same pull request review process as any other code change (see [.github/CONTRIBUTING.md](../.github/CONTRIBUTING.md)) before merging to `main`.

## Obtaining dependencies

* Packages are installed from the public [npm registry](https://www.npmjs.com/).
* `package-lock.json` is committed to the repository and used for reproducible installs — the exact resolved version of every direct and transitive dependency is pinned.
* The `packageManager` field in `package.json` pins the npm version used to install and build the project.
* The `allowScripts` field in `package.json` explicitly allowlists which packages are permitted to run install-time (postinstall) scripts. It's npm's own native field (npm ≥ 11.16.0), managed via `npm approve-scripts` / `npm deny-scripts`, not a third-party tool — today it's advisory (npm flags unreviewed scripts but still runs them), with a future npm release expected to block unapproved scripts by default. Any package added here should have a concrete reason (e.g. a native module that needs to compile a binary during install).
* The `overrides` field forces a specific version of a transitive dependency when a direct dependency's own declared range still permits a vulnerable release:
  * `socket.io-parser: 4.2.7` patches [CVE-2026-33151](https://github.com/socketio/socket.io/security/advisories/GHSA-677m-j7p3-52f9) (resource exhaustion via unbounded binary attachments, fixed in 4.2.6) and [CVE-2026-69185](https://github.com/advisories/GHSA-2m8v-j782-fhvr) (zero-attachment memory exhaustion, fixed in 4.2.7). Needed because `socket.io`/`socket.io-client` declare `socket.io-parser: ~4.2.4`, a range that still allows the unpatched 4.2.4–4.2.6.
  * `engine.io: ^6.6.10` patches [GHSA-2gc4-cqfq-p2gv](https://github.com/advisories/GHSA-2gc4-cqfq-p2gv) (DoS via an Engine.IO protocol revision mismatch). Needed because `socket.io@4.8.3` declares `engine.io: ~6.6.0`, a range that still allows the unpatched 6.6.0–6.6.9.
  * `@esbuild-kit/core-utils`'s `esbuild` dependency is bumped to `^0.25.0` to patch the esbuild dev-server request-forwarding issue ([GHSA-67mh-4wv8-2f99](https://github.com/advisories/GHSA-67mh-4wv8-2f99)). Needed because `drizzle-kit` pulls in `@esbuild-kit/esm-loader` → `@esbuild-kit/core-utils`, which pins `esbuild: ~0.18.20`.
  * `body-parser: 1.20.6` patches [CVE-2026-12590](https://github.com/expressjs/body-parser/security/advisories/GHSA-v422-hmwv-36x6) (invalid `limit` values silently disabling size enforcement). Needed because `express` bundles `body-parser: ~1.20.5`.
  * `qs: ^6.16.0` patches [CVE-2026-82417](https://github.com/advisories/GHSA-4mjr-xmp4-gh2g) (DoS via attacker-controlled `isBuffer`, affecting `>=2.2.5 <6.16.0`) and [CVE-2026-82562](https://github.com/advisories/GHSA-x5fp-wj9c-mxmx) (array-limit bypass via bracket-key comma parsing, affecting `>=6.14.2 <=6.15.3`). Needed because `express` and `body-parser` both pin `qs: ~6.15.1`, which excludes the patched `6.16.0` — npm's only other remedy was a semver-major bump to `express@5`. The override also covers `openid`, `steam-web` and `superagent`, whose own ranges likewise still permit a vulnerable release.
  * `brace-expansion: ^5.0.12` patches [GHSA-6j4f-fj2g-mc7p](https://github.com/advisories/GHSA-6j4f-fj2g-mc7p) and [GHSA-qhr7-859c-m2p7](https://github.com/advisories/GHSA-qhr7-859c-m2p7) (stack exhaustion via uncontrolled recursion, fixed in 5.0.10 and 5.0.11) and [GHSA-q2hr-2g5m-vwhr](https://github.com/advisories/GHSA-q2hr-2g5m-vwhr) (quadratic-time `{a},b}` rewrite, fixed in 5.0.12). It was previously pinned at `^5.0.9`, which patched [CVE-2026-69152](https://github.com/advisories/GHSA-rgw5-rvv9-x895) (DoS via unbounded intermediate arrays, bypassing the [CVE-2026-14257](https://github.com/advisories/GHSA-mh99-v99m-4gvg) mitigation). Needed because `archiver` → `readdir-glob` → `minimatch` would resolve to a version below `5.0.9` without this override; the override was previously pinned at `^5.0.8`, which patched CVE-2026-14257 but was itself within the range vulnerable to CVE-2026-69152 (`4.0.0`–`5.0.8`). The same floor also covers [CVE-2026-13149](https://github.com/advisories/GHSA-3jxr-9vmj-r5cp) (exponential-time expansion of consecutive `{}` groups, fixed in 5.0.8).
  * `fast-uri: ^3.1.8` also patches [GHSA-hrr3-gc8f-f4qj](https://github.com/advisories/GHSA-hrr3-gc8f-f4qj) (inconsistent host case normalization via percent-encoded octets, fixed in 3.1.8). The earlier `^3.1.7` floor patched seven HIGH advisories: [CVE-2026-16221](https://github.com/advisories/GHSA-v2hh-gcrm-f6hx) (fixed in 3.1.4), [CVE-2026-18446](https://github.com/advisories/GHSA-7p8r-x3mc-p8w7) (backslash authority introducer, fixed in 3.1.5), [CVE-2026-75931](https://github.com/advisories/GHSA-5jgf-p345-68v8) and [CVE-2026-76172](https://github.com/advisories/GHSA-jqff-g426-hqxp) (host confusion via skipped IDN/percent-encoded scheme normalization), [CVE-2026-75975](https://github.com/advisories/GHSA-f65p-4m7j-42xc) and [CVE-2026-75899](https://github.com/advisories/GHSA-fph4-wmhf-6fwf) (SSRF via malformed IPv6/repeated hostname percent-decoding normalization), and [CVE-2026-84292](https://github.com/advisories/GHSA-qw65-cvwx-89v3) (authority injection via an unvalidated port in `serialize`). Needed because `ajv@8.20.0`'s own declared range (`^3.0.1`, then `^3.1.5`) kept allowing an unpatched release. `ajv` is a shared transitive dependency of both `secretlint` (dev-only) and the production `@hookform/resolvers` (as a `peerOptional` dependency), so despite earlier notes here, `fast-uri` **is** reachable in production — confirmed by `npm audit --omit=dev` flagging it directly.
  * `proxy-addr: ^2.0.8` patches [CVE-2026-90711](https://vuldb.com/cve/CVE-2026-90711) ([AIKIDO-2026-101201](https://security.aikido.dev/cve/AIKIDO-2026-101201), critical: accepts undersized IPv4-mapped IPv6 trust subnets, letting unauthenticated clients spoof `X-Forwarded-For` and bypass IP-based access controls, rate limiting, and audit logging), affecting `>=1.1.0 <=2.0.7`. Needed because `express` pins `proxy-addr: ~2.0.7`, which had not yet bumped its declared range to include the patched `2.0.8`.
  * `ip-address: ^10.7.2` patches [CVE-2026-101913](https://github.com/advisories/GHSA-rpw4-54j3-4h4q) and [CVE-2026-101910](https://github.com/advisories/GHSA-2vr4-cq9g-pvrc) (affecting `<=10.5.0`). Needed because `express-rate-limit` (`^10.2.0`) and `socks` (`^10.1.1`) still allow a vulnerable release.
  * `node-gyp`'s `undici` dependency is bumped to `^6.29.0` to patch [CVE-2026-85024](https://github.com/advisories/GHSA-3wwx-pv8p-q78v) (affecting `6.25.0`–`6.28.0`). Scoped to `node-gyp` (reached via the dev-only `@lizenz/checker`) because the app's own direct `undici` dependency already carries the same fix on the 8.x line (8.10.2). Needed because `node-gyp` declares `undici: ^6.25.0`.
  * `eslint-plugin-react`'s `eslint` dependency is bumped to `^10.9.1` to allow ESLint v10 support. Needed because `eslint-plugin-react@7.37.2` officially supports only up to `eslint@^9.7`, but the linting rules in ESLint v10 are stricter and require updating the codebase to comply. This override is temporary — once `eslint-plugin-react` releases a new major version with official ESLint v10 support, it can be removed.
  * All of the above should be revisited (and likely removed) once the upstream packages bump their own internal dependency ranges past the vulnerable versions.
  * The `check-overrides` CI job (`npm run check:overrides`, see [`scripts/check-overrides.mjs`](../scripts/check-overrides.mjs)) checks this automatically on every PR and fails once an override is no longer needed, so there's no need to track removal manually.

## Tracking and updates

[Dependabot](https://docs.github.com/en/code-security/dependabot) is configured in [`.github/dependabot.yml`](../.github/dependabot.yml) to check for updates weekly (Monday) for both npm dependencies and GitHub Actions used in CI:

* Updates are opened as grouped pull requests (e.g. React-related packages, Radix UI components, dev vs. production dependencies, and all GitHub Actions bumps) to keep the PR volume manageable.
* Semver-major bumps are proposed automatically like any other update rather than excluded, since silently skipping them meant a major-version-only security fix could go unnoticed; they aren't folded into the minor/patch groups, so they still land as their own PR and get individual review.
* Every dependency-update PR runs through the same CI gate as any other change — lint, type check, the full test suite, and a Docker build (see [`.github/workflows/ci.yml`](../.github/workflows/ci.yml)) — before it can be merged.

## Release-time visibility

Every published Docker image ships with a generated Software Bill of Materials listing the exact versions of every dependency included in that release. See [docs/SBOM.md](SBOM.md) for how to inspect it.

## Currently blocked updates

Tracked here so a blocked Dependabot PR doesn't get silently re-proposed and re-investigated from scratch. Remove an entry once its update is unblocked and merged.

*As of 2026-07-04, `release/1.4.0`:*

* **`@hookform/resolvers`** `3.10.0` → `5.4.0` (PR #756) — blocked. Installs, but the TypeScript check fails in form resolver usage (`client/src/pages/downloaders.tsx`, `client/src/pages/indexers.tsx`). The project is on Zod 3 (`zod: ^3.25.0`); this upgrade likely needs resolver/schema compatibility adjustments first.
* **React 19** `react 18.3.1` → `19.2.7`, `@types/react 18.3.11` → `19.2.17` (PR #761) — blocked. Install fails on peer dependency resolution across UI dependencies; needs a broader compatibility pass across the React ecosystem packages first.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.