security: harden production configuration and routes
Run Tests on Branches / Detect Changes (push) Successful in 12s
Run Tests on Branches / Frontend Tests (push) Successful in 2m12s
Run Tests on Branches / Frontend Mobile Tests (push) Has been skipped
Run Tests on Branches / Parapharmacy API Tests (push) Successful in 2m2s
Run Tests on Branches / PIP Platform Tests (push) Has been skipped
Run Tests on Branches / Backend Tests (push) Successful in 2m8s

This commit is contained in:
Antoni Nuñez Romeu
2026-07-22 17:24:54 +02:00
parent f60af5f6b2
commit 849763896d
21 changed files with 638 additions and 68 deletions
@@ -0,0 +1,101 @@
# FarmaFinder Security Dependency and Release Hardening Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Remove the remaining high/critical dependency and supply-chain risks, make Python and container builds reproducible, and establish deployment-blocking security verification after the configuration and access-control hotfixes.
**Architecture:** Upgrade dependencies in isolated package-family batches while preserving the existing runtime security controls. Resolve Python dependencies into a committed `uv.lock`, pin container inputs by immutable digests, and run dependency, image, and secret scans in CI. Any remaining advisory is recorded with its path, exploitability, mitigation, and owner.
**Tech Stack:** npm workspaces/package-lock, Node.js 20/24, Python 3.13, uv, pip-audit, Docker Compose, Trivy, Gitleaks, Jest, Vitest, pytest.
---
## Files and responsibilities
- Create `docs/security/2026-07-22-dependency-hardening.md`: audit baseline, selected versions/digests, residual-advisory decisions, and verification evidence.
- Create `apps/pip-platform/uv.lock`: resolved, hash-pinned Python dependency graph.
- Modify `apps/backend/package.json`, `apps/parapharmacy-api/package.json`, `apps/frontend/package.json`, `apps/scraper/package.json`, and the root `package-lock.json` for isolated dependency batches.
- Modify both Node Dockerfiles, Compose files, and deployment docs for immutable images and lockfile-enforced installs.
- Create `.github/workflows/security.yml`: reproducible installs, tests, audits, secret scanning, image scanning, and Compose checks.
## Baseline to preserve
The preceding hotfix plan already added production secret validation, service-key middleware, protected parapharmacy mutations, internal Compose networking, production-safe Swagger behavior, and security regression tests. Do not revert those controls. The last online audit reported 56 advisories for the backend/workspace scope and 3 for the parapharmacy API; counts must be refreshed before each batch.
### Task 1: Establish an auditable dependency baseline
**Files:** Create `docs/security/2026-07-22-dependency-hardening.md`.
- [ ] Run `npm ci` from the repository root, then run `npm audit --json`, `npm audit --prefix apps/backend --json`, `npm audit --prefix apps/parapharmacy-api --json`, `npm audit --prefix apps/frontend --json`, and `npm audit --prefix apps/scraper --json`, saving reports only under `/tmp` and never recording secret values.
- [ ] Record counts, direct versions, Node/npm/Python/uv/Docker versions, dependency paths, available fixes, and whether each finding reaches a production image.
- [ ] Confirm no unrelated lockfile rewrite exists with `git diff --check` and `git status --short`.
- [ ] Commit the ledger with `git add docs/security/2026-07-22-dependency-hardening.md && git commit -m "docs: record dependency hardening baseline"`.
### Task 2: Create and verify the Python lockfile
**Files:** Create `apps/pip-platform/uv.lock`; update PIP deployment docs if present.
- [ ] Run `cd apps/pip-platform && uv lock`; do not hand-edit generated lock content.
- [ ] Recreate from the lock with `uv sync --frozen --extra dev`, then run `uv run pytest -q` and `uv run pip-audit --strict`.
- [ ] If `pip-audit` is absent, add it to the development dependency group, rerun `uv lock`, and repeat the frozen sync. Record each Python advisory with package, path, reachability, and owner.
- [ ] Commit with `git add apps/pip-platform/uv.lock && git commit -m "build: lock pip platform dependencies"`.
### Task 3: Pin runtime container inputs immutably
**Files:** Root/PIP Compose files, both Node Dockerfiles, and the dependency-hardening ledger.
- [ ] Replace every runtime `:latest` image with an approved release. Resolve digests with `docker buildx imagetools inspect redis:7-alpine`, `postgres:16-alpine`, `mongo:7`, the approved n8n release, the approved Redis exporter release, and the approved PostgreSQL exporter release.
- [ ] Replace each reference with `repository:tag@sha256:` followed by the exact digest returned by `docker buildx imagetools inspect`, record the UTC update date and approver, and verify the digest is for the deployment platform.
- [ ] Ensure each Node Dockerfile copies its matching `package.json` and lockfile before `npm ci --omit=dev`; build both images and run a startup/config smoke test.
- [ ] Commit the image/Dockerfile batch separately so it can be reverted without undoing dependency code.
### Task 4: Upgrade backend dependency families independently
**Files:** `apps/backend/package.json`, root `package-lock.json`, existing backend tests.
- [ ] Run `npm ci` and `npm test --prefix apps/backend -- --runInBand` before changing versions.
- [ ] Upgrade all direct OpenTelemetry packages as one compatible family: API, auto-instrumentations, exporters, instrumentation-pino, resources, SDKs, and semantic conventions. Do not upgrade only `auto-instrumentations-node`.
- [ ] Regenerate only through npm, inspect the lockfile for unrelated upgrades, and rerun the backend suite.
- [ ] In a separate batch, upgrade `bcrypt` and `sqlite3`; verify native installs under Node 20 and 24, session/database tests, `npm ls tar node-gyp`, and `npm audit --prefix apps/backend --audit-level=high`.
- [ ] Never use `npm audit fix --force`; any major upgrade requires a compatibility note and review. Commit each family separately.
### Task 5: Upgrade parapharmacy and scraper dependency families
**Files:** `apps/parapharmacy-api/package.json`, `apps/scraper/package.json`, root `package-lock.json`, security tests.
- [ ] Upgrade Mongoose within its supported major, regenerate the lockfile, and confirm `npm ls fast-uri` resolves outside the audited range.
- [ ] Run `npm test --prefix apps/parapharmacy-api -- --runInBand __tests__/security.test.js` and `npm audit --prefix apps/parapharmacy-api --audit-level=high`.
- [ ] Upgrade scraper Puppeteer dependencies only after recording the current executable path. Preserve `PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true` and `/usr/bin/chromium`; verify with `node -e "console.log(process.env.PUPPETEER_EXECUTABLE_PATH || '/usr/bin/chromium')"`.
- [ ] Run scraper module-load/available tests and commit Mongoose and scraper batches separately.
### Task 6: Upgrade frontend tooling without exposing Vitest UI
**Files:** `apps/frontend/package.json`, root `package-lock.json`, Vite/Vitest config, CI workflow.
- [ ] Confirm no production or CI command uses Vitest UI with `rg -n "vitest( --ui|.*ui)" apps/frontend package.json .github`.
- [ ] Upgrade Vite, Rollup/esbuild, and Vitest as a compatible toolchain; keep React plugin, jsdom, and testing-library versions compatible with the selected Vitest major.
- [ ] Regenerate the lockfile and run `npm test --prefix apps/frontend`, `npm run build --prefix apps/frontend`, and `npm audit --prefix apps/frontend --audit-level=high`.
- [ ] Record any development-only residual advisory and commit this batch separately.
### Task 7: Add deployment-blocking CI gates
**Files:** Create `.github/workflows/security.yml`.
- [ ] Add pull-request/protected-branch jobs for `npm ci` plus all Node tests/builds; workspace/app `npm audit --audit-level=high`; `uv sync --frozen`, pytest, and `pip-audit --strict`; Gitleaks full-history scanning; Trivy high/critical image scanning; and root/PIP Compose rendering.
- [ ] The Compose job must use fixture values and assert that only intended frontend/API ports are published, no internal database/exporter ports are published, and no production-secret `${...:-placeholder}` fallback remains.
- [ ] Build production images with committed lockfiles, scan image digests, upload JSON reports as artifacts, and never upload `.env` files or secret values.
- [ ] Pin third-party actions to reviewed immutable commit SHAs and grant read-only repository permissions. Commit with `git add .github/workflows/security.yml && git commit -m "ci: enforce dependency and image security gates"`.
### Task 8: Run final verification and residual-advisory review
**Files:** Update the dependency-hardening ledger only if verification exposes a regression or documented exception.
- [ ] Run `npm ci`, backend tests, parapharmacy security tests, frontend tests/build, `uv sync --frozen --extra dev`, `uv run pytest`, and `uv run pip-audit --strict`.
- [ ] Render all Compose files with production-like fixture variables; inspect for placeholders, mutable tags, public database/exporter ports, and missing required secrets.
- [ ] Build all production images and black-box test public GETs, 401 unauthenticated mutations, 403 invalid keys, absent production Swagger, and absent host-published internal infrastructure.
- [ ] Re-run all audits. Every remaining high/critical item must list package, dependency path, production reachability, exploitability, mitigation, owner, and review/expiry date; unexplained high/critical findings block deployment.
- [ ] Run `git diff --check`, confirm no real `.env` is tracked, attach command counts to the ledger, and commit the final evidence.
## Self-review
This plan covers the remaining audit findings: dependency-family upgrades, Python locking/auditing, immutable images, lockfile-enforced Docker installs, secret scanning, image scanning, frontend/Vitest exposure, and residual-advisory review. It deliberately avoids forced major upgrades and keeps each risky family in a reversible batch.