Problem
The production lockfile retains known-vulnerable packages. The directly declared fs-js-lite FamilySearch client depends on abandoned request, which in turn retains vulnerable/deprecated transitive packages including uuid@3. The current audit also flags the React Router and Socket.IO parser chains; Socket.IO client is declared but has no application import, while React Router is actively bundled. Existing overrides update only selected request children and do not remove the vulnerable HTTP client itself.
Evidence
The root manifest declares the affected FamilySearch client:
Its resolved production package pulls in request:
"node_modules/fs-js-lite": {
"version": "2.6.6",
"dependencies": { "js-cookie": "^2.2.0", "request": "^2.78.0" }
}
The server initializes that client for production FamilySearch requests and invokes it through the shared fetcher:
import FamilySearch from 'fs-js-lite';
export const fsc = new FamilySearch({ environment: 'production', ... });
...
fsc.get(url, (error: Error | null, response: any) => {
The lockfile also resolves react-router-dom@7.17.0 and socket.io-parser@4.2.6; the UI uses BrowserRouter, but repository search finds no application import or socket creation for the declared socket.io-client package. A current production-only npm audit against the audited snapshot reported zero critical, two high, four moderate, and one low advisory.
Impact
The server ships an obsolete HTTP stack for authenticated FamilySearch traffic, leaving known request/uuid advisory paths in the runtime dependency graph. The client also installs a vulnerable Socket.IO parsing chain despite not using it, expanding the shipped supply-chain surface. A malicious or malformed upstream response, crafted navigation, or future call site that passes attacker-controlled transport input can inherit the advisory behavior; the stale lockfile prevents a clean production vulnerability gate.
Implementation plan
- Record the exact advisory IDs and fixed-version ranges with a fresh
npm audit --omit=dev --package-lock-only in CI-capable networking before changing versions; preserve the audit JSON in CI logs rather than committing it.
- Replace
fs-js-lite with a maintained FamilySearch API adapter built on Node fetch (or a maintained SDK that has no vulnerable production chain). Preserve the narrow fscget<T>(path) interface, fixed FamilySearch base URL, bearer-token behavior, retry/error classification, and test seams; do not accept arbitrary absolute URLs.
- Migrate
server/src/lib/familysearch/client.ts and fetcher.ts callers, then remove fs-js-lite, request, its overrides, and orphaned transitive packages through a normal npm install --package-lock-only update.
- Update React Router to the audit-fixed release compatible with the current
BrowserRouter usage and add a route smoke test for direct/deep links.
- Remove
socket.io-client if the repository-wide import check remains empty; otherwise update it and its parser to an audit-fixed compatible release and add a connection/parser regression test. Do not add a Socket.IO server merely to justify the dependency.
- Add a CI production dependency audit (
npm audit --omit=dev --package-lock-only) that fails for high/critical findings, with a narrowly documented temporary exception only when a verified non-reachable advisory lacks an upstream fix.
Acceptance criteria
Verification
Run focused unit tests for the FamilySearch adapter and fetcher with mocked success, unauthorized, retryable, and malformed-response cases; run the client route smoke/deep-link test; then run npm test -- --run, npm run build, npm ci --ignore-scripts, and npm audit --omit=dev --package-lock-only.
Dependencies and related work
None. This does not alter the staged data migration work in #120 or #149-#155; keep the adapter boundary compatible with current JSON/SQLite-backed callers.
Scope
Complexity: Complex. Likely files: root/client manifests and lockfile, server/src/lib/familysearch/client.ts, server/src/lib/familysearch/fetcher.ts, their tests, client bootstrap/routing tests, and CI workflow. Non-goals: changing FamilySearch record models, modifying browser scraping, or migrating the data stores.
Problem
The production lockfile retains known-vulnerable packages. The directly declared
fs-js-liteFamilySearch client depends on abandonedrequest, which in turn retains vulnerable/deprecated transitive packages includinguuid@3. The current audit also flags the React Router and Socket.IO parser chains; Socket.IO client is declared but has no application import, while React Router is actively bundled. Existing overrides update only selectedrequestchildren and do not remove the vulnerable HTTP client itself.Evidence
The root manifest declares the affected FamilySearch client:
Its resolved production package pulls in
request:The server initializes that client for production FamilySearch requests and invokes it through the shared fetcher:
The lockfile also resolves
react-router-dom@7.17.0andsocket.io-parser@4.2.6; the UI usesBrowserRouter, but repository search finds no application import or socket creation for the declaredsocket.io-clientpackage. A current production-only npm audit against the audited snapshot reported zero critical, two high, four moderate, and one low advisory.Impact
The server ships an obsolete HTTP stack for authenticated FamilySearch traffic, leaving known
request/uuidadvisory paths in the runtime dependency graph. The client also installs a vulnerable Socket.IO parsing chain despite not using it, expanding the shipped supply-chain surface. A malicious or malformed upstream response, crafted navigation, or future call site that passes attacker-controlled transport input can inherit the advisory behavior; the stale lockfile prevents a clean production vulnerability gate.Implementation plan
npm audit --omit=dev --package-lock-onlyin CI-capable networking before changing versions; preserve the audit JSON in CI logs rather than committing it.fs-js-litewith a maintained FamilySearch API adapter built on Nodefetch(or a maintained SDK that has no vulnerable production chain). Preserve the narrowfscget<T>(path)interface, fixed FamilySearch base URL, bearer-token behavior, retry/error classification, and test seams; do not accept arbitrary absolute URLs.server/src/lib/familysearch/client.tsandfetcher.tscallers, then removefs-js-lite,request, its overrides, and orphaned transitive packages through a normalnpm install --package-lock-onlyupdate.BrowserRouterusage and add a route smoke test for direct/deep links.socket.io-clientif the repository-wide import check remains empty; otherwise update it and its parser to an audit-fixed compatible release and add a connection/parser regression test. Do not add a Socket.IO server merely to justify the dependency.npm audit --omit=dev --package-lock-only) that fails for high/critical findings, with a narrowly documented temporary exception only when a verified non-reachable advisory lacks an upstream fix.Acceptance criteria
fs-js-lite,request, and their vulnerable transitive chain are absent from the production lockfile.socket.io-clientis either removed as unused or updated with an exercised consumer.Verification
Run focused unit tests for the FamilySearch adapter and fetcher with mocked success, unauthorized, retryable, and malformed-response cases; run the client route smoke/deep-link test; then run
npm test -- --run,npm run build,npm ci --ignore-scripts, andnpm audit --omit=dev --package-lock-only.Dependencies and related work
None. This does not alter the staged data migration work in #120 or #149-#155; keep the adapter boundary compatible with current JSON/SQLite-backed callers.
Scope
Complexity: Complex. Likely files: root/client manifests and lockfile,
server/src/lib/familysearch/client.ts,server/src/lib/familysearch/fetcher.ts, their tests, client bootstrap/routing tests, and CI workflow. Non-goals: changing FamilySearch record models, modifying browser scraping, or migrating the data stores.