This document describes how Questarr selects, obtains, and tracks its dependencies.
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) before merging to main.
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.packageManager field in package.json pins the npm version used to install and build the project.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).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 (resource exhaustion via unbounded binary attachments, fixed in 4.2.6) and CVE-2026-69185 (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 (DoS via an Engine.IO protocol revision mismatch). Needed because socket.io@4.8.4 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). Needed because drizzle-kit pulls in @esbuild-kit/esm-loader → @esbuild-kit/core-utils, which pins esbuild: ~0.18.20.qs: ^6.16.0 patches CVE-2026-82417 (DoS via attacker-controlled isBuffer, affecting >=2.2.5 <6.16.0) and CVE-2026-82562 (array-limit bypass via bracket-key comma parsing, affecting >=6.14.2 <=6.15.3). Needed because express and body-parser still pin qs to a range that excludes the patched 6.16.0, and openid, steam-web and superagent have ranges that likewise still permit a vulnerable release.brace-expansion: ^5.0.12 patches GHSA-6j4f-fj2g-mc7p and GHSA-qhr7-859c-m2p7 (stack exhaustion via uncontrolled recursion, fixed in 5.0.10 and 5.0.11) and 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 (DoS via unbounded intermediate arrays, bypassing the CVE-2026-14257 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 (exponential-time expansion of consecutive {} groups, fixed in 5.0.8).fast-uri: ^3.1.8 also patches 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 (fixed in 3.1.4), CVE-2026-18446 (backslash authority introducer, fixed in 3.1.5), CVE-2026-75931 and CVE-2026-76172 (host confusion via skipped IDN/percent-encoded scheme normalization), CVE-2026-75975 and CVE-2026-75899 (SSRF via malformed IPv6/repeated hostname percent-decoding normalization), and CVE-2026-84292 (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.ip-address: ^10.7.2 patches CVE-2026-101913 and CVE-2026-101910 (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 (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.fast-copy: ^4.1.0 patches GHSA-jggr-w7fw-pc2j (stack exhaustion when copying deeply nested values, fixed in 4.1.0). Dev-only. Needed because pino-pretty declares fast-copy: ^4.0.0, which still allows the unpatched 4.0.0–4.0.4.follow-redirects: ^1.16.1 patches GHSA-q3jh-wrc6-jgq8 (array-form headers bypass cross-origin credential stripping) and GHSA-8r9p-f939-6h3c (sensitiveHeaders regex escaping can expose credential headers), both affecting 1.16.0. Needed because axios declares follow-redirects: ^1.16.0, which still permits the vulnerable release.postcss-selector-parser: ^7.1.6 patches CVE-2026-104844 (quadratic complexity in flat selector parsing, fixed in 7.1.6). Dev-only. Needed because @npmcli/query declares postcss-selector-parser: ^7.0.0. The 6.x line has no fix; its only consumer, the unused @tailwindcss/typography, was removed rather than forced across a major version.body-parser: ^2.4.0 patches GHSA-27r3-jxmh-p828 (DoS via trailing bytes after a compressed request body, affecting 2.3.0). Needed because express@5.3.0 declares body-parser: ^2.3.0, a range that still allows the vulnerable release. The direct multer dependency is bumped to ^2.5.0 for GHSA-q7qp-rjg7-q26m (DoS via a pending asynchronous fileFilter after request teardown, fixed in 2.5.0).check-overrides CI job (npm run check:overrides, see 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.Dependabot is configured in .github/dependabot.yml to check for updates weekly (Monday) for both npm dependencies and GitHub Actions used in CI:
.github/workflows/ci.yml) — before it can be merged.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 for how to inspect it.
Resolved in 1.5.0: React 19, matching React type packages, Zod 4, and
@hookform/resolvers 5 are supported.