security(deps): bump @sveltejs/kit + vite to clear BODY_SIZE_LIMIT bypass + 5 high devDep CVEs #458

Open
opened 2026-05-07 17:21:33 +02:00 by marcel · 8 comments
Owner

Context

Pre-prod audit (Appendix A.2 of docs/audits/2026-05-07-pre-prod-architectural-review.md) ran npm audit --json against frontend/. Production deps are clean (0 vulnerabilities), but dev/transitive deps have 12 advisories — 7 HIGH, 4 MODERATE, 1 LOW. Notably, two HIGHs are in direct production dependencies (@sveltejs/kit and vite).

Direct production-dep CVEs (must fix)

  • GHSA-3f6h-2hrp-w5wx (HIGH, @sveltejs/kit): Unvalidated redirect in handle hook causes Denial-of-Service.
  • GHSA-2crg-3p73-43xp (HIGH, @sveltejs/adapter-node): BODY_SIZE_LIMIT bypass — combines badly with audit F-12 (no AV scan) to allow large adversarial uploads.
  • GHSA-4w7w-66w2-5vf9 (HIGH, vite): Path traversal in optimized-deps .map handling.
  • GHSA-v2wj-q39q-566r (HIGH, vite): server.fs.deny bypass with queries.
  • GHSA-p9ff-h696-f583 (HIGH, vite): Arbitrary file read via dev-server WebSocket.

Transitive moderate/high CVEs cleared by npm update

  • kysely SQL injection (transitive via paraglide).
  • picomatch ReDoS, flatted prototype pollution, postcss XSS, brace-expansion ReDoS, uuid bounds check, yaml stack overflow.

Approach

cd frontend
npm update @sveltejs/kit @sveltejs/adapter-node vite
npm update                 # picks up patched transitives
npm audit --omit=dev       # confirm production set is still clean
npm audit                  # confirm dev set has no remaining HIGH
npm run check              # type-check still passes
npm run test               # vitest suite still passes

If a dep refuses to update because of a peer constraint, document the residual CVE and the upstream blocker in this issue.

Critical files

  • frontend/package.json
  • frontend/package-lock.json

Verification

  1. npm audit --omit=dev returns 0 vulnerabilities.
  2. npm audit --audit-level=high returns 0 advisories at HIGH or CRITICAL.
  3. npm run check && npm run test && npm run build all pass.
  4. docker compose build frontend && docker compose up -d frontend healthy.

Acceptance criteria

  • @sveltejs/kit is at the patched version listed in GHSA-3f6h-2hrp-w5wx (≥ 2.50.0 or current latest).
  • vite is at the patched version listed in GHSA-4w7w-66w2-5vf9 (≥ 7.3.0 or current latest).
  • npm audit --omit=dev reports 0 vulnerabilities.
  • No remaining HIGH advisories in npm audit --audit-level=high.
  • Frontend tests + build still pass.

Effort

S — 1 hour including verification.

Risk if not addressed

BODY_SIZE_LIMIT bypass + missing AV scan = an attacker can upload arbitrarily large malicious files. Vite path-traversal and dev-server WebSocket arbitrary-read are dev-time-only but expose the developer host during local work.

Tracked in audit doc as part of F-22 (dependency hygiene).

## Context Pre-prod audit (Appendix A.2 of `docs/audits/2026-05-07-pre-prod-architectural-review.md`) ran `npm audit --json` against `frontend/`. Production deps are clean (0 vulnerabilities), but dev/transitive deps have **12 advisories** — 7 HIGH, 4 MODERATE, 1 LOW. Notably, two HIGHs are in **direct production dependencies** (`@sveltejs/kit` and `vite`). ### Direct production-dep CVEs (must fix) - **GHSA-3f6h-2hrp-w5wx** (HIGH, `@sveltejs/kit`): Unvalidated redirect in `handle` hook causes Denial-of-Service. - **GHSA-2crg-3p73-43xp** (HIGH, `@sveltejs/adapter-node`): `BODY_SIZE_LIMIT` bypass — combines badly with audit F-12 (no AV scan) to allow large adversarial uploads. - **GHSA-4w7w-66w2-5vf9** (HIGH, `vite`): Path traversal in optimized-deps `.map` handling. - **GHSA-v2wj-q39q-566r** (HIGH, `vite`): `server.fs.deny` bypass with queries. - **GHSA-p9ff-h696-f583** (HIGH, `vite`): Arbitrary file read via dev-server WebSocket. ### Transitive moderate/high CVEs cleared by `npm update` - `kysely` SQL injection (transitive via paraglide). - `picomatch` ReDoS, `flatted` prototype pollution, `postcss` XSS, `brace-expansion` ReDoS, `uuid` bounds check, `yaml` stack overflow. ## Approach ```bash cd frontend npm update @sveltejs/kit @sveltejs/adapter-node vite npm update # picks up patched transitives npm audit --omit=dev # confirm production set is still clean npm audit # confirm dev set has no remaining HIGH npm run check # type-check still passes npm run test # vitest suite still passes ``` If a dep refuses to update because of a peer constraint, document the residual CVE and the upstream blocker in this issue. ## Critical files - `frontend/package.json` - `frontend/package-lock.json` ## Verification 1. `npm audit --omit=dev` returns 0 vulnerabilities. 2. `npm audit --audit-level=high` returns 0 advisories at HIGH or CRITICAL. 3. `npm run check && npm run test && npm run build` all pass. 4. `docker compose build frontend && docker compose up -d frontend` healthy. ## Acceptance criteria - [ ] `@sveltejs/kit` is at the patched version listed in GHSA-3f6h-2hrp-w5wx (≥ 2.50.0 or current latest). - [ ] `vite` is at the patched version listed in GHSA-4w7w-66w2-5vf9 (≥ 7.3.0 or current latest). - [ ] `npm audit --omit=dev` reports 0 vulnerabilities. - [ ] No remaining HIGH advisories in `npm audit --audit-level=high`. - [ ] Frontend tests + build still pass. ## Effort S — 1 hour including verification. ## Risk if not addressed `BODY_SIZE_LIMIT` bypass + missing AV scan = an attacker can upload arbitrarily large malicious files. Vite path-traversal and dev-server WebSocket arbitrary-read are dev-time-only but expose the developer host during local work. Tracked in audit doc as part of **F-22** (dependency hygiene).
marcel added this to the Production v1 milestone 2026-05-07 17:21:33 +02:00
marcel added the P1-highsecurity labels 2026-05-07 17:23:30 +02:00
Author
Owner

👨‍💻 Markus Keller — Application Architect

Observations

  • Installed versions confirm exposure. package-lock.json shows @sveltejs/kit@2.55.0 (vulnerable ≤2.57.0) and vite@7.3.1 (vulnerable ≤7.3.1). Both are one minor/patch bump away from the fix. No schema changes, no new routes, no new services — the blast radius of this bump is confined to frontend/package.json + package-lock.json.
  • adapter-node ships no explicit BODY_SIZE_LIMIT in docker-compose.yml or svelte.config.js. The built artefact (build/handler.js) reads env('BODY_SIZE_LIMIT', '512K') — meaning the default 512 KB cap is active, but the bypass (GHSA-2crg-3p73-43xp) makes that cap unenforced until the kit version is updated. The combination with audit finding F-12 (no AV scan) is correctly flagged in the issue.
  • Vite CVEs are dev-time only. GHSA-4w7w-66w2-5vf9 (.map path traversal), GHSA-v2wj-q39q-566r (fs.deny bypass), and GHSA-p9ff-h696-f583 (WebSocket arbitrary file read) are all in the Vite dev server. In production the adapter-node builds a standalone server that does not use Vite's dev server at all. The production exposure is the @sveltejs/kit pair, not Vite. The Vite fix still matters for developer workstation protection.
  • renovate.json exists but is misconfigured for this issue. The file has no platform: "gitea", no automerge, and no matchDepTypes rule that would catch dev-dependency CVEs automatically. This is a systemic gap that caused the 12 advisories to accumulate rather than being caught as they appeared.
  • No doc updates needed for this PR. Dependency version bumps in package.json touch none of the doc-update triggers (no new routes, no schema changes, no new packages, no new architecture decisions).

Recommendations

  1. Execute the approach exactly as written in the issue. The four-command sequence (npm update @sveltejs/kit @sveltejs/adapter-node vite && npm update && npm audit --omit=dev && npm audit --audit-level=high) is the correct, minimal intervention. Do not pin to a specific version string — let semver do its job.
  2. After the bump, add an explicit BODY_SIZE_LIMIT env var to docker-compose.yml under the frontend service, set to a value appropriate for the largest expected upload payload (e.g. 50M if PDFs up to ~50 MB are expected). Making the cap explicit prevents the default from silently changing under a future kit upgrade.
  3. Fix renovate.json in a follow-up issue. Add "platform": "gitea", "automerge": true for patch updates, and "automergeType": "pr" for minor updates requiring review. This PR should not be blocked on that, but the gap should be tracked.
  4. No ADR needed. A dependency version bump does not constitute an architectural decision with lasting structural consequences. Don't over-document this.
## 👨‍💻 Markus Keller — Application Architect ### Observations - **Installed versions confirm exposure.** `package-lock.json` shows `@sveltejs/kit@2.55.0` (vulnerable ≤2.57.0) and `vite@7.3.1` (vulnerable ≤7.3.1). Both are one minor/patch bump away from the fix. No schema changes, no new routes, no new services — the blast radius of this bump is confined to `frontend/package.json` + `package-lock.json`. - **`adapter-node` ships no explicit `BODY_SIZE_LIMIT`** in `docker-compose.yml` or `svelte.config.js`. The built artefact (`build/handler.js`) reads `env('BODY_SIZE_LIMIT', '512K')` — meaning the default 512 KB cap is active, but the *bypass* (GHSA-2crg-3p73-43xp) makes that cap unenforced until the kit version is updated. The combination with audit finding F-12 (no AV scan) is correctly flagged in the issue. - **Vite CVEs are dev-time only.** GHSA-4w7w-66w2-5vf9 (`.map` path traversal), GHSA-v2wj-q39q-566r (`fs.deny` bypass), and GHSA-p9ff-h696-f583 (WebSocket arbitrary file read) are all in the Vite dev server. In production the adapter-node builds a standalone server that does not use Vite's dev server at all. The production exposure is the `@sveltejs/kit` pair, not Vite. The Vite fix still matters for developer workstation protection. - **`renovate.json` exists but is misconfigured** for this issue. The file has no `platform: "gitea"`, no `automerge`, and no `matchDepTypes` rule that would catch dev-dependency CVEs automatically. This is a systemic gap that caused the 12 advisories to accumulate rather than being caught as they appeared. - **No doc updates needed for this PR.** Dependency version bumps in `package.json` touch none of the doc-update triggers (no new routes, no schema changes, no new packages, no new architecture decisions). ### Recommendations 1. **Execute the approach exactly as written in the issue.** The four-command sequence (`npm update @sveltejs/kit @sveltejs/adapter-node vite && npm update && npm audit --omit=dev && npm audit --audit-level=high`) is the correct, minimal intervention. Do not pin to a specific version string — let semver do its job. 2. **After the bump, add an explicit `BODY_SIZE_LIMIT` env var** to `docker-compose.yml` under the `frontend` service, set to a value appropriate for the largest expected upload payload (e.g. `50M` if PDFs up to ~50 MB are expected). Making the cap explicit prevents the default from silently changing under a future kit upgrade. 3. **Fix `renovate.json` in a follow-up issue.** Add `"platform": "gitea"`, `"automerge": true` for patch updates, and `"automergeType": "pr"` for minor updates requiring review. This PR should not be blocked on that, but the gap should be tracked. 4. **No ADR needed.** A dependency version bump does not constitute an architectural decision with lasting structural consequences. Don't over-document this.
Author
Owner

🔐 Nora "NullX" Steiner — Security Engineer

Observations

  • Severity classifications in the issue title are inflated vs. npm audit reality. The issue calls all five GHSA entries "HIGH," but npm audit --json classifies them as: GHSA-3f6h-2hrp-w5wx (SvelteKit DoS redirect) = moderate; GHSA-2crg-3p73-43xp (BODY_SIZE_LIMIT bypass) = high; GHSA-4w7w-66w2-5vf9 (Vite .map path traversal) = moderate; GHSA-v2wj-q39q-566r (Vite fs.deny bypass) = high; GHSA-p9ff-h696-f583 (Vite WebSocket file read) = high. This doesn't change the remediation priority, but accurate classification matters for future audit comparisons.
  • BODY_SIZE_LIMIT bypass (GHSA-2crg-3p73-43xp) is the one production-relevant CVE. The issue correctly identifies this. The current install (@sveltejs/kit@2.55.0, @sveltejs/adapter-node@5.5.4) is in the vulnerable range (≤2.57.0). The built handler.js shows the default 512 KB limit, but the bypass means this limit is not reliably enforced: a crafted multipart request can exceed it. Combined with the absence of file-type validation at the backend boundary and no AV scan (finding F-12 from the audit), an attacker can upload oversized malicious payloads.
  • All three Vite CVEs are dev-server only — zero production exposure. vite-plugin-devtools-json is in devDependencies; the production adapter runs a Node HTTP server, not Vite's dev server. GHSA-p9ff-h696-f583 (WebSocket arbitrary file read) is only exploitable when vite dev is running. The developer workstation is still an attack surface worth closing, but this is not a production risk.
  • Transitive HIGH advisories: kysely SQL injection (via @inlang/paraglide-js) is worth understanding. Kysely is used by Paraglide for its own internals — it is not a direct query channel for application data. If Paraglide does not pass user input into Kysely queries, this is a packaging artifact, not an exploitable path in this application. Still, bump it with npm update.
  • flatted (prototype pollution, HIGH) and picomatch (ReDoS, HIGH) are pure transitive dev-tool deps. Not production-exposed.
  • No regression test exists for the BODY_SIZE_LIMIT fix. The verification steps in the issue are manual (npm audit --omit=dev). That's appropriate — this vulnerability class doesn't lend itself to a unit test. The acceptance criteria (0 vulnerabilities on --omit=dev, 0 HIGH on --audit-level=high) are the right test oracle here.
  • renovate.json has no Gitea platform config and no security-patch automerge. This is directly why 12 advisories accumulated. A properly configured Renovate would have auto-merged the patch that fixed these CVEs within days of publication.

Recommendations

  1. Treat GHSA-2crg-3p73-43xp as the P0 production risk and GHSA-v2wj-q39q-566r + GHSA-p9ff-h696-f583 as P1 (developer workstation). Communicate the distinction clearly in the PR description so reviewers understand relative urgency.
  2. After bumping, verify the BODY_SIZE_LIMIT is enforced by testing a request exceeding 512 KB directly against the running SvelteKit node server (before the backend). A curl -X POST -F "file=@large.pdf" http://localhost:3000/api/documents with a 10 MB file should return 413 once the patched version is deployed.
  3. Add platform: "gitea" and security-patch automerge to renovate.json in a follow-up issue (P2, but create the issue now). Reference the pre-prod audit finding F-22. Every day without Renovate properly configured is a day these CVEs could re-enter undetected.
  4. Add npm audit --audit-level=high as a CI gate in .gitea/workflows/ci.yml. Insert it as a step in the unit-tests job after npm ci. It takes under 10 seconds and blocks merges when a HIGH advisory enters the tree. This directly addresses finding F-22 from the architectural review.
  5. File-type validation at the backend boundary (separate issue) — the BODY_SIZE_LIMIT bypass is a necessary fix, but the upstream defence-in-depth gap (no content-type whitelist enforcement at FileService, no magic-byte check) should be tracked as a distinct issue referencing F-12.

Open Decisions

  • BODY_SIZE_LIMIT value for production: The current default is 512 KB, which is far below the expected PDF upload size. Should this be set explicitly in docker-compose.yml before going live, and if so, what is the largest document the system should accept? This affects both the node adapter limit and any reverse-proxy client_max_body_size that Tobias configures in Caddy. The two values must be consistent.
## 🔐 Nora "NullX" Steiner — Security Engineer ### Observations - **Severity classifications in the issue title are inflated vs. npm audit reality.** The issue calls all five GHSA entries "HIGH," but `npm audit --json` classifies them as: GHSA-3f6h-2hrp-w5wx (SvelteKit DoS redirect) = **moderate**; GHSA-2crg-3p73-43xp (BODY_SIZE_LIMIT bypass) = **high**; GHSA-4w7w-66w2-5vf9 (Vite `.map` path traversal) = **moderate**; GHSA-v2wj-q39q-566r (Vite `fs.deny` bypass) = **high**; GHSA-p9ff-h696-f583 (Vite WebSocket file read) = **high**. This doesn't change the remediation priority, but accurate classification matters for future audit comparisons. - **BODY_SIZE_LIMIT bypass (GHSA-2crg-3p73-43xp) is the one production-relevant CVE.** The issue correctly identifies this. The current install (`@sveltejs/kit@2.55.0`, `@sveltejs/adapter-node@5.5.4`) is in the vulnerable range (≤2.57.0). The built `handler.js` shows the default 512 KB limit, but the bypass means this limit is not reliably enforced: a crafted multipart request can exceed it. Combined with the absence of file-type validation at the backend boundary and no AV scan (finding F-12 from the audit), an attacker can upload oversized malicious payloads. - **All three Vite CVEs are dev-server only — zero production exposure.** `vite-plugin-devtools-json` is in devDependencies; the production adapter runs a Node HTTP server, not Vite's dev server. GHSA-p9ff-h696-f583 (WebSocket arbitrary file read) is only exploitable when `vite dev` is running. The developer workstation is still an attack surface worth closing, but this is not a production risk. - **Transitive HIGH advisories: `kysely` SQL injection** (via `@inlang/paraglide-js`) is worth understanding. Kysely is used by Paraglide for its own internals — it is not a direct query channel for application data. If Paraglide does not pass user input into Kysely queries, this is a packaging artifact, not an exploitable path in this application. Still, bump it with `npm update`. - **`flatted` (prototype pollution, HIGH) and `picomatch` (ReDoS, HIGH)** are pure transitive dev-tool deps. Not production-exposed. - **No regression test exists for the BODY_SIZE_LIMIT fix.** The verification steps in the issue are manual (`npm audit --omit=dev`). That's appropriate — this vulnerability class doesn't lend itself to a unit test. The acceptance criteria (0 vulnerabilities on `--omit=dev`, 0 HIGH on `--audit-level=high`) are the right test oracle here. - **`renovate.json` has no Gitea platform config and no security-patch automerge.** This is directly why 12 advisories accumulated. A properly configured Renovate would have auto-merged the patch that fixed these CVEs within days of publication. ### Recommendations 1. **Treat GHSA-2crg-3p73-43xp as the P0 production risk** and GHSA-v2wj-q39q-566r + GHSA-p9ff-h696-f583 as P1 (developer workstation). Communicate the distinction clearly in the PR description so reviewers understand relative urgency. 2. **After bumping, verify the BODY_SIZE_LIMIT is enforced** by testing a request exceeding 512 KB directly against the running SvelteKit node server (before the backend). A `curl -X POST -F "file=@large.pdf" http://localhost:3000/api/documents` with a 10 MB file should return 413 once the patched version is deployed. 3. **Add `platform: "gitea"` and security-patch automerge to `renovate.json`** in a follow-up issue (P2, but create the issue now). Reference the pre-prod audit finding F-22. Every day without Renovate properly configured is a day these CVEs could re-enter undetected. 4. **Add `npm audit --audit-level=high` as a CI gate** in `.gitea/workflows/ci.yml`. Insert it as a step in the `unit-tests` job after `npm ci`. It takes under 10 seconds and blocks merges when a HIGH advisory enters the tree. This directly addresses finding F-22 from the architectural review. 5. **File-type validation at the backend boundary** (separate issue) — the BODY_SIZE_LIMIT bypass is a necessary fix, but the upstream defence-in-depth gap (no content-type whitelist enforcement at `FileService`, no magic-byte check) should be tracked as a distinct issue referencing F-12. ### Open Decisions - **`BODY_SIZE_LIMIT` value for production:** The current default is 512 KB, which is far below the expected PDF upload size. Should this be set explicitly in `docker-compose.yml` before going live, and if so, what is the largest document the system should accept? This affects both the node adapter limit and any reverse-proxy `client_max_body_size` that Tobias configures in Caddy. The two values must be consistent.
Author
Owner

🛠️ Felix Brandt — Fullstack Developer

Observations

  • The fix is mechanical — no code logic changes. npm update @sveltejs/kit @sveltejs/adapter-node vite && npm update touches only package-lock.json and the version ranges in package.json. There are no API surface changes, no breaking changes in the SvelteKit 2.55.0→2.58.x or vite 7.3.1→7.3.2 changelog that affect application code.
  • Installed versions confirmed: @sveltejs/kit@2.55.0, vite@7.3.1, @sveltejs/adapter-node@5.5.4 — all in vulnerable ranges. npm update resolves to the latest semver-compatible version within the declared ^ ranges.
  • The verification suite listed in the issue is correct and complete. npm run check && npm run test && npm run build covers type-checking, unit/component tests, and build. The missing step is npm run lint — add it between check and test to catch any formatter regressions in the lock file diff.
  • svelte.config.js is minimal: adapter({ }) with no options. The BODY_SIZE_LIMIT bypass fix ships with the @sveltejs/kit bump, not via config changes. No svelte.config.js edits are needed.
  • renovate.json is present but has no automerge or Gitea platform config. This is a dev-workflow gap, not a blocker for this PR. The issue is correctly scoped to the dependency bump itself.
  • TDD note: A security CVE of this type (HTTP body parsing bypass) cannot be meaningfully unit-tested in Vitest — the fix lives inside the adapter's request handling. The acceptance criteria (npm audit --omit=dev → 0) are the right test oracle. No failing test to write before the fix here.

Recommendations

  1. Run the commands in exactly the stated order. npm update @sveltejs/kit @sveltejs/adapter-node vite first (direct deps), then npm update (transitive cleanup). Doing npm update alone may not fully resolve the direct dep constraints.
  2. Add npm run lint to the verification sequence in the issue — the full verification should be: npm audit --omit=dev && npm audit --audit-level=high && npm run lint && npm run check && npm run test && npm run build. This matches the CI pipeline exactly.
  3. Commit the lockfile change as a standalone atomic commit with message security(deps): bump @sveltejs/kit and vite to clear 5 high CVEs. Do not bundle any unrelated change into this commit — the lockfile diff will be large enough on its own (many transitive hashes change).
  4. After bumping, verify vite.config.ts is unaffected. The optimizeDeps.include array (pdfjs-dist, @tiptap/*) and the proxy config should function identically in vite 7.3.2. Do a quick npm run dev smoke test before pushing.
## 🛠️ Felix Brandt — Fullstack Developer ### Observations - **The fix is mechanical — no code logic changes.** `npm update @sveltejs/kit @sveltejs/adapter-node vite && npm update` touches only `package-lock.json` and the version ranges in `package.json`. There are no API surface changes, no breaking changes in the SvelteKit 2.55.0→2.58.x or vite 7.3.1→7.3.2 changelog that affect application code. - **Installed versions confirmed:** `@sveltejs/kit@2.55.0`, `vite@7.3.1`, `@sveltejs/adapter-node@5.5.4` — all in vulnerable ranges. `npm update` resolves to the latest semver-compatible version within the declared `^` ranges. - **The verification suite listed in the issue is correct and complete.** `npm run check && npm run test && npm run build` covers type-checking, unit/component tests, and build. The missing step is `npm run lint` — add it between `check` and `test` to catch any formatter regressions in the lock file diff. - **`svelte.config.js` is minimal: `adapter({ })` with no options.** The `BODY_SIZE_LIMIT` bypass fix ships with the `@sveltejs/kit` bump, not via config changes. No `svelte.config.js` edits are needed. - **`renovate.json` is present but has no automerge or Gitea platform** config. This is a dev-workflow gap, not a blocker for this PR. The issue is correctly scoped to the dependency bump itself. - **TDD note:** A security CVE of this type (HTTP body parsing bypass) cannot be meaningfully unit-tested in Vitest — the fix lives inside the adapter's request handling. The acceptance criteria (`npm audit --omit=dev` → 0) are the right test oracle. No failing test to write before the fix here. ### Recommendations 1. **Run the commands in exactly the stated order.** `npm update @sveltejs/kit @sveltejs/adapter-node vite` first (direct deps), then `npm update` (transitive cleanup). Doing `npm update` alone may not fully resolve the direct dep constraints. 2. **Add `npm run lint` to the verification sequence** in the issue — the full verification should be: `npm audit --omit=dev && npm audit --audit-level=high && npm run lint && npm run check && npm run test && npm run build`. This matches the CI pipeline exactly. 3. **Commit the lockfile change as a standalone atomic commit** with message `security(deps): bump @sveltejs/kit and vite to clear 5 high CVEs`. Do not bundle any unrelated change into this commit — the lockfile diff will be large enough on its own (many transitive hashes change). 4. **After bumping, verify `vite.config.ts` is unaffected.** The `optimizeDeps.include` array (`pdfjs-dist`, `@tiptap/*`) and the proxy config should function identically in vite 7.3.2. Do a quick `npm run dev` smoke test before pushing.
Author
Owner

🚀 Tobias Wendt — DevOps & Platform Engineer

Observations

  • docker-compose.yml has no BODY_SIZE_LIMIT env var on the frontend service. The adapter falls back to its compiled default (512 KB as seen in build/handler.js). The BODY_SIZE_LIMIT bypass CVE (GHSA-2crg-3p73-43xp) means this default is unenforced until the kit is patched. After the bump, the 512 KB default will be enforced — but 512 KB will reject any normal PDF upload, so this needs an explicit value before production.
  • No client_max_body_size or equivalent in the reverse proxy config. The Caddy configuration is not in the repo (infra/ is a stub), but based on the architectural review, there's no Caddyfile committed. The SvelteKit node adapter's BODY_SIZE_LIMIT and Caddy's max_body must agree, or one layer will reject requests the other would have passed. This is a deployment-time coordination item.
  • renovate.json is not configured for Gitea and has no automerge. Without "platform": "gitea", Renovate may not connect to the self-hosted instance at all. The 12 accumulated advisories are a direct consequence — each one had a fix available (all fixAvailable: true) but no automation created a PR. This is the systemic issue behind finding F-22.
  • The CI workflow (ci.yml) has no npm audit gate. Lint, tests, and build run — but a HIGH advisory can merge undetected. Adding npm audit --audit-level=high --omit=dev as a CI step would have flagged these 7 advisories before they merged.
  • Docker image for the frontend is built from ./frontend/Dockerfile. After the bump, a docker compose build frontend is required to pick up the new packages in the production image. The issue correctly includes this as a verification step.
  • The frontend_node_modules named volume in docker-compose.yml means the host-mounted source and the container's node_modules are separate. After npm update on the host, docker compose build frontend rebuilds the image with the updated packages — the named volume is a dev convenience, not a concern for production builds.

Recommendations

  1. Set BODY_SIZE_LIMIT explicitly in docker-compose.yml under frontend.environment. Decide on the maximum upload size first (see Open Decisions), then set it consistently here and in the Caddy reverse proxy config when that is committed. A mismatch where Caddy allows 100 MB but the adapter rejects at 512 KB will cause confusing 413 errors.
  2. Add npm audit --audit-level=high --omit=dev to ci.yml as a step in the unit-tests job, immediately after npm ci. This is a one-liner that takes under 10 seconds and prevents this class of issue from merging in future:
    - name: Security audit
      run: npm audit --audit-level=high --omit=dev
      working-directory: frontend
    
  3. Fix renovate.json for Gitea in a separate issue/PR (reference F-22). Add "platform": "gitea", "endpoint": "http://heim-nas:3005/api/v1", and "automerge": true for patch updates. This is the highest-leverage infrastructure change for long-term dependency hygiene at essentially zero cost.
  4. After the bump, run the full docker verification as stated in the issue: docker compose build frontend && docker compose up -d frontend. Then verify with docker compose ps frontend that the container is healthy before closing the issue.

Open Decisions

  • BODY_SIZE_LIMIT value: What is the maximum document size the system should accept? Historical Kurrent/Sütterlin documents scanned at 300 DPI run 2–15 MB per page as TIFF/PNG, or 500 KB–5 MB as PDF. Setting BODY_SIZE_LIMIT=50M in the adapter and client_max_body_size 52m in Caddy (slightly larger to allow HTTP overhead) is a reasonable production starting point — but this needs to be a deliberate decision, not a default. The two values must be aligned.
## 🚀 Tobias Wendt — DevOps & Platform Engineer ### Observations - **`docker-compose.yml` has no `BODY_SIZE_LIMIT` env var** on the `frontend` service. The adapter falls back to its compiled default (512 KB as seen in `build/handler.js`). The BODY_SIZE_LIMIT bypass CVE (GHSA-2crg-3p73-43xp) means this default is unenforced until the kit is patched. After the bump, the 512 KB default will be enforced — but 512 KB will reject any normal PDF upload, so this needs an explicit value before production. - **No `client_max_body_size` or equivalent in the reverse proxy config.** The Caddy configuration is not in the repo (`infra/` is a stub), but based on the architectural review, there's no Caddyfile committed. The SvelteKit node adapter's `BODY_SIZE_LIMIT` and Caddy's `max_body` must agree, or one layer will reject requests the other would have passed. This is a deployment-time coordination item. - **`renovate.json` is not configured for Gitea and has no automerge.** Without `"platform": "gitea"`, Renovate may not connect to the self-hosted instance at all. The 12 accumulated advisories are a direct consequence — each one had a fix available (all `fixAvailable: true`) but no automation created a PR. This is the systemic issue behind finding F-22. - **The CI workflow (`ci.yml`) has no `npm audit` gate.** Lint, tests, and build run — but a HIGH advisory can merge undetected. Adding `npm audit --audit-level=high --omit=dev` as a CI step would have flagged these 7 advisories before they merged. - **Docker image for the frontend is built from `./frontend/Dockerfile`.** After the bump, a `docker compose build frontend` is required to pick up the new packages in the production image. The issue correctly includes this as a verification step. - **The `frontend_node_modules` named volume** in `docker-compose.yml` means the host-mounted source and the container's `node_modules` are separate. After `npm update` on the host, `docker compose build frontend` rebuilds the image with the updated packages — the named volume is a dev convenience, not a concern for production builds. ### Recommendations 1. **Set `BODY_SIZE_LIMIT` explicitly in `docker-compose.yml`** under `frontend.environment`. Decide on the maximum upload size first (see Open Decisions), then set it consistently here and in the Caddy reverse proxy config when that is committed. A mismatch where Caddy allows 100 MB but the adapter rejects at 512 KB will cause confusing 413 errors. 2. **Add `npm audit --audit-level=high --omit=dev` to `ci.yml`** as a step in the `unit-tests` job, immediately after `npm ci`. This is a one-liner that takes under 10 seconds and prevents this class of issue from merging in future: ```yaml - name: Security audit run: npm audit --audit-level=high --omit=dev working-directory: frontend ``` 3. **Fix `renovate.json` for Gitea** in a separate issue/PR (reference F-22). Add `"platform": "gitea"`, `"endpoint": "http://heim-nas:3005/api/v1"`, and `"automerge": true` for patch updates. This is the highest-leverage infrastructure change for long-term dependency hygiene at essentially zero cost. 4. **After the bump, run the full docker verification** as stated in the issue: `docker compose build frontend && docker compose up -d frontend`. Then verify with `docker compose ps frontend` that the container is healthy before closing the issue. ### Open Decisions - **`BODY_SIZE_LIMIT` value:** What is the maximum document size the system should accept? Historical Kurrent/Sütterlin documents scanned at 300 DPI run 2–15 MB per page as TIFF/PNG, or 500 KB–5 MB as PDF. Setting `BODY_SIZE_LIMIT=50M` in the adapter and `client_max_body_size 52m` in Caddy (slightly larger to allow HTTP overhead) is a reasonable production starting point — but this needs to be a deliberate decision, not a default. The two values must be aligned.
Author
Owner

📋 Elicit — Requirements Engineer

Observations

  • The issue spec is well-formed and implementation-ready. It contains a clear context, a precise approach (4 commands), a specific list of critical files, verifiable acceptance criteria with measurable exit conditions, an effort estimate, and a risk statement. This is above-average quality for a security dependency bump issue.
  • Severity language in the issue body diverges from tooling output. The issue labels all five GHSA entries "HIGH" but npm audit reports GHSA-3f6h-2hrp-w5wx and GHSA-4w7w-66w2-5vf9 as moderate, not high. This is not a blocking gap, but misclassification in an issue body can lead to incorrect future triage — if someone re-runs npm audit and sees "moderate" where the issue says "HIGH," they may underestimate the discrepancy.
  • Acceptance criterion for @sveltejs/adapter-node is missing. The issue requires @sveltejs/kit ≥ 2.50.0 and vite ≥ 7.3.0 but does not state the required version of @sveltejs/adapter-node. Since GHSA-2crg-3p73-43xp (BODY_SIZE_LIMIT bypass) is the primary production CVE and it ships via adapter-node, a version criterion for that package would make the acceptance criteria complete. Currently @sveltejs/adapter-node@5.5.4 is installed; the fix was released in 5.6.0 — this should be stated.
  • "Risk if not addressed" section correctly identifies the compound risk (BODY_SIZE_LIMIT bypass + absent AV scan = oversized malicious upload), but does not state the risk of the Vite dev CVEs to developer workstations. A brief note ("Vite CVEs expose developer machines running npm run dev, not the production server") would prevent future readers from over- or under-reacting.
  • Effort estimate "S — 1 hour" is accurate for the pure dependency bump. However, if the BODY_SIZE_LIMIT explicit configuration and the CI audit gate (both recommended by other reviewers) are included in this issue's scope, the effort is closer to S+. The issue should either explicitly include or explicitly exclude those tasks from scope.
  • The follow-on systemic issue (Renovate misconfiguration) is not tracked anywhere. This issue closes F-22 partially (patching current CVEs) but not structurally (preventing future CVE accumulation).

Recommendations

  1. Correct the severity labels in the issue body — change GHSA-3f6h-2hrp-w5wx and GHSA-4w7w-66w2-5vf9 from "HIGH" to "MODERATE" to match npm audit output. This keeps the issue as the source of truth for future auditors.
  2. Add an acceptance criterion for @sveltejs/adapter-node: @sveltejs/adapter-node is at ≥ 5.6.0 (the patched version for GHSA-2crg-3p73-43xp).
  3. Explicitly scope out the Renovate fix and the CI audit gate from this issue, or expand the scope — pick one. Leaving them as implicit "should also do" creates scope drift. Create a separate issue for Renovate configuration (referencing F-22) and another for adding npm audit to CI, each with their own acceptance criteria.
  4. Add a sentence to "Risk if not addressed" clarifying that the Vite CVEs are developer-workstation risks, not production server risks. This helps the reader prioritise correctly and is consistent with the issue's goal of accurate risk communication.
## 📋 Elicit — Requirements Engineer ### Observations - **The issue spec is well-formed and implementation-ready.** It contains a clear context, a precise approach (4 commands), a specific list of critical files, verifiable acceptance criteria with measurable exit conditions, an effort estimate, and a risk statement. This is above-average quality for a security dependency bump issue. - **Severity language in the issue body diverges from tooling output.** The issue labels all five GHSA entries "HIGH" but `npm audit` reports GHSA-3f6h-2hrp-w5wx and GHSA-4w7w-66w2-5vf9 as **moderate**, not high. This is not a blocking gap, but misclassification in an issue body can lead to incorrect future triage — if someone re-runs `npm audit` and sees "moderate" where the issue says "HIGH," they may underestimate the discrepancy. - **Acceptance criterion for `@sveltejs/adapter-node` is missing.** The issue requires `@sveltejs/kit ≥ 2.50.0` and `vite ≥ 7.3.0` but does not state the required version of `@sveltejs/adapter-node`. Since GHSA-2crg-3p73-43xp (BODY_SIZE_LIMIT bypass) is the primary production CVE and it ships via `adapter-node`, a version criterion for that package would make the acceptance criteria complete. Currently `@sveltejs/adapter-node@5.5.4` is installed; the fix was released in `5.6.0` — this should be stated. - **"Risk if not addressed" section correctly identifies the compound risk** (BODY_SIZE_LIMIT bypass + absent AV scan = oversized malicious upload), but does not state the risk of the Vite dev CVEs to developer workstations. A brief note ("Vite CVEs expose developer machines running `npm run dev`, not the production server") would prevent future readers from over- or under-reacting. - **Effort estimate "S — 1 hour" is accurate** for the pure dependency bump. However, if the `BODY_SIZE_LIMIT` explicit configuration and the CI audit gate (both recommended by other reviewers) are included in this issue's scope, the effort is closer to S+. The issue should either explicitly include or explicitly exclude those tasks from scope. - **The follow-on systemic issue (Renovate misconfiguration)** is not tracked anywhere. This issue closes F-22 partially (patching current CVEs) but not structurally (preventing future CVE accumulation). ### Recommendations 1. **Correct the severity labels in the issue body** — change GHSA-3f6h-2hrp-w5wx and GHSA-4w7w-66w2-5vf9 from "HIGH" to "MODERATE" to match `npm audit` output. This keeps the issue as the source of truth for future auditors. 2. **Add an acceptance criterion for `@sveltejs/adapter-node`:** `@sveltejs/adapter-node is at ≥ 5.6.0 (the patched version for GHSA-2crg-3p73-43xp).` 3. **Explicitly scope out the Renovate fix and the CI audit gate** from this issue, or expand the scope — pick one. Leaving them as implicit "should also do" creates scope drift. Create a separate issue for Renovate configuration (referencing F-22) and another for adding `npm audit` to CI, each with their own acceptance criteria. 4. **Add a sentence to "Risk if not addressed"** clarifying that the Vite CVEs are developer-workstation risks, not production server risks. This helps the reader prioritise correctly and is consistent with the issue's goal of accurate risk communication.
Author
Owner

🧪 Sara Holt — QA Engineer

Observations

  • No automated security gate exists for this CVE class in CI. The .gitea/workflows/ci.yml pipeline runs lint, unit/component tests (Vitest), OCR unit tests, and backend unit/integration tests — but no npm audit step. This means all 12 current advisories (7 HIGH, 4 MODERATE, 1 LOW) would have merged into main without any CI warning.
  • The verification steps in the issue are correct but unordered for efficiency. The issue lists verification in this order: npm update commands → npm audit --omit=devnpm audit --audit-level=highnpm run checknpm run testnpm run builddocker compose build/up. This is the right sequence — fast static checks first, expensive build last.
  • npm run lint is absent from the verification steps. The CI pipeline runs lint; the verification steps should match CI exactly. A lockfile change (large package-lock.json diff) is unlikely to trigger a lint failure, but omitting it means the manual verification diverges from the automated gate.
  • The acceptance criteria are measurable and verifiable — exactly what makes a good quality gate: npm audit --omit=dev → 0 vulnerabilities, npm audit --audit-level=high → 0 high advisories, npm run check && npm run test && npm run build → all pass, docker compose build && up → healthy. These criteria map directly to CI steps and can be verified without human judgment.
  • No regression test is appropriate for this CVE type. GHSA-2crg-3p73-43xp (BODY_SIZE_LIMIT bypass) is a transport-layer bug in the adapter — it cannot be unit-tested with Vitest. The correct regression guard is the npm audit gate in CI, not a test file.
  • Vitest suite currently has 0 failures (post the recent pre-existing test fixes in this branch). The bump must preserve this. A quick npm test after the update is essential before committing.
  • The @vitest/browser-playwright package (^4.0.10) and related dev packages are unlikely to be affected by the bump, but the browser component tests should be explicitly confirmed to pass — they run against real Chromium and are the most brittle part of the suite.

Recommendations

  1. Add npm audit --audit-level=high --omit=dev as a CI step in .gitea/workflows/ci.yml, in the unit-tests job after npm ci and before lint. This is the most valuable QA change this issue can deliver beyond the bump itself, and it closes the systemic gap permanently:
    - name: Security audit (no dev deps)
      run: npm audit --audit-level=high --omit=dev
      working-directory: frontend
    
  2. Update the verification sequence in the issue to include npm run lint as step 5, between npm run check and npm run test. This makes the manual checklist match CI exactly.
  3. Explicitly run the browser component tests as part of verification — npm test runs all Vitest projects including the browser project. Confirm the output shows the browser project passing, not just the server project.
  4. Mark each acceptance criterion as checked before closing the issue. The issue has a checkbox-style AC list — these should all be ticked with the actual resolved version numbers noted (e.g., @sveltejs/kit resolved to 2.58.x) rather than just closing the issue after the PR merges.
## 🧪 Sara Holt — QA Engineer ### Observations - **No automated security gate exists for this CVE class in CI.** The `.gitea/workflows/ci.yml` pipeline runs lint, unit/component tests (Vitest), OCR unit tests, and backend unit/integration tests — but no `npm audit` step. This means all 12 current advisories (7 HIGH, 4 MODERATE, 1 LOW) would have merged into main without any CI warning. - **The verification steps in the issue are correct but unordered for efficiency.** The issue lists verification in this order: `npm update` commands → `npm audit --omit=dev` → `npm audit --audit-level=high` → `npm run check` → `npm run test` → `npm run build` → `docker compose build/up`. This is the right sequence — fast static checks first, expensive build last. - **`npm run lint` is absent from the verification steps.** The CI pipeline runs lint; the verification steps should match CI exactly. A lockfile change (large `package-lock.json` diff) is unlikely to trigger a lint failure, but omitting it means the manual verification diverges from the automated gate. - **The acceptance criteria are measurable and verifiable** — exactly what makes a good quality gate: `npm audit --omit=dev` → 0 vulnerabilities, `npm audit --audit-level=high` → 0 high advisories, `npm run check && npm run test && npm run build` → all pass, `docker compose build && up` → healthy. These criteria map directly to CI steps and can be verified without human judgment. - **No regression test is appropriate for this CVE type.** GHSA-2crg-3p73-43xp (BODY_SIZE_LIMIT bypass) is a transport-layer bug in the adapter — it cannot be unit-tested with Vitest. The correct regression guard is the `npm audit` gate in CI, not a test file. - **Vitest suite currently has 0 failures** (post the recent pre-existing test fixes in this branch). The bump must preserve this. A quick `npm test` after the update is essential before committing. - **The `@vitest/browser-playwright` package** (`^4.0.10`) and related dev packages are unlikely to be affected by the bump, but the browser component tests should be explicitly confirmed to pass — they run against real Chromium and are the most brittle part of the suite. ### Recommendations 1. **Add `npm audit --audit-level=high --omit=dev` as a CI step** in `.gitea/workflows/ci.yml`, in the `unit-tests` job after `npm ci` and before lint. This is the most valuable QA change this issue can deliver beyond the bump itself, and it closes the systemic gap permanently: ```yaml - name: Security audit (no dev deps) run: npm audit --audit-level=high --omit=dev working-directory: frontend ``` 2. **Update the verification sequence in the issue** to include `npm run lint` as step 5, between `npm run check` and `npm run test`. This makes the manual checklist match CI exactly. 3. **Explicitly run the browser component tests** as part of verification — `npm test` runs all Vitest projects including the browser project. Confirm the output shows the browser project passing, not just the server project. 4. **Mark each acceptance criterion as checked before closing the issue.** The issue has a checkbox-style AC list — these should all be ticked with the actual resolved version numbers noted (e.g., `@sveltejs/kit resolved to 2.58.x`) rather than just closing the issue after the PR merges.
Author
Owner

🎨 Leonie Voss — UI/UX Design Lead

Observations

  • This issue has no UI/UX surface area. Dependency version bumps to @sveltejs/kit, @sveltejs/adapter-node, and vite are infrastructure-layer changes. No Svelte components change, no routes change, no visual output changes. From a design perspective, this is a zero-impact issue.
  • One indirect UX consideration worth noting: upload size limits. The BODY_SIZE_LIMIT bypass (GHSA-2crg-3p73-43xp) fix will make the 512 KB limit actually enforced. If the current UI allows users to upload PDFs larger than 512 KB — which it almost certainly does, given the document archival use case — then enforcing 512 KB without raising the limit first would silently break the upload flow with a 413 error. The user-facing impact of that would be: the upload appears to succeed client-side (progress bar fills), then fails server-side, with no clear error message shown to the user unless the error handling in documents/new/ maps 413 responses explicitly.
  • I checked: the upload route (/documents/new/) uses a standard form action. If the SvelteKit adapter rejects the body before it reaches the form action, SvelteKit may return a raw 413 with no localized error message — the GlobalExceptionHandler on the Spring Boot side wouldn't even be invoked, since the rejection happens at the adapter layer.

Recommendations

  1. Raise BODY_SIZE_LIMIT before deploying the patched adapter. The fix must not accidentally enforce 512 KB in production — that would break every PDF upload. Set an explicit value in docker-compose.yml that reflects the actual maximum document size (see the open decision raised by Nora and Tobias).
  2. Verify the upload error UX after the bump. Once BODY_SIZE_LIMIT is set to a real value (e.g. 50 MB), test uploading a file that exceeds it. Confirm that the user sees a meaningful error message rather than a blank 413 page. If the 413 is not caught by the form action's error handler, add a mapping in the upload flow.

No design review needed beyond these two points — this is primarily a security/infrastructure concern.

## 🎨 Leonie Voss — UI/UX Design Lead ### Observations - **This issue has no UI/UX surface area.** Dependency version bumps to `@sveltejs/kit`, `@sveltejs/adapter-node`, and `vite` are infrastructure-layer changes. No Svelte components change, no routes change, no visual output changes. From a design perspective, this is a zero-impact issue. - **One indirect UX consideration worth noting: upload size limits.** The BODY_SIZE_LIMIT bypass (GHSA-2crg-3p73-43xp) fix will make the 512 KB limit actually enforced. If the current UI allows users to upload PDFs larger than 512 KB — which it almost certainly does, given the document archival use case — then enforcing 512 KB without raising the limit first would silently break the upload flow with a 413 error. The user-facing impact of that would be: the upload appears to succeed client-side (progress bar fills), then fails server-side, with no clear error message shown to the user unless the error handling in `documents/new/` maps 413 responses explicitly. - **I checked: the upload route (`/documents/new/`)** uses a standard form action. If the SvelteKit adapter rejects the body before it reaches the form action, SvelteKit may return a raw 413 with no localized error message — the `GlobalExceptionHandler` on the Spring Boot side wouldn't even be invoked, since the rejection happens at the adapter layer. ### Recommendations 1. **Raise `BODY_SIZE_LIMIT` before deploying the patched adapter.** The fix must not accidentally enforce 512 KB in production — that would break every PDF upload. Set an explicit value in `docker-compose.yml` that reflects the actual maximum document size (see the open decision raised by Nora and Tobias). 2. **Verify the upload error UX after the bump.** Once `BODY_SIZE_LIMIT` is set to a real value (e.g. 50 MB), test uploading a file that exceeds it. Confirm that the user sees a meaningful error message rather than a blank 413 page. If the 413 is not caught by the form action's error handler, add a mapping in the upload flow. No design review needed beyond these two points — this is primarily a security/infrastructure concern.
Author
Owner

Decision Queue — Open Items Requiring Human Judgment

Consolidated from the multi-persona review. Each item needs a decision before this issue can be fully closed. Items are grouped by theme.


Theme 1: BODY_SIZE_LIMIT — What value, and where?

Raised by: Nora (Security), Tobias (DevOps), Leonie (UX)

The problem: Patching the GHSA-2crg-3p73-43xp bypass means the adapter's BODY_SIZE_LIMIT will be enforced for the first time. The current default is 512 KB, which will reject every normal PDF upload. This limit must be raised before deploying the patched adapter, not after.

What needs deciding:

  1. What is the maximum document size this system should accept? Historical Kurrent/Sütterlin documents at 300 DPI scan to 500 KB–15 MB as PDF. A practical ceiling of 50 MB covers multi-page originals without being reckless.
  2. Who sets the limit? It needs to be set in two coordinated places:
    • docker-compose.yml: BODY_SIZE_LIMIT=50M under frontend.environment
    • Caddy reverse proxy client_max_body_size (not yet in repo — needs to be present before production go-live)
  3. Does the 413 error surface correctly in the UI? If the adapter rejects the body before SvelteKit's form action runs, the GlobalExceptionHandler on the Spring Boot side is never invoked. The upload route (/documents/new/) may show a raw 413 rather than a localized error. This needs a quick manual test after the limit is set.

Recommendation from the review panel (non-binding): Set BODY_SIZE_LIMIT=50M in docker-compose.yml as part of this PR, and create a follow-up issue to test the 413 UX path.


Theme 2: Scope of this issue — bump only, or also CI gate + Renovate?

Raised by: Elicit (Requirements), Sara (QA), Tobias (DevOps), Nora (Security)

The problem: All four personas independently recommend adding npm audit --audit-level=high --omit=dev as a CI gate and fixing renovate.json for Gitea. These are the systemic fixes that prevent this class of issue from recurring. They are currently not in scope for this issue.

What needs deciding: Should this issue's scope expand to include:

  • Adding npm audit --audit-level=high --omit=dev to .gitea/workflows/ci.yml (15-minute task)
  • Fixing renovate.json with Gitea platform config and patch automerge (30-minute task)

Or should these become separate issues that are created and prioritized alongside this one?

Recommendation from the review panel: Include the CI audit gate in this PR (it is a one-liner with no risk). Create a separate issue for Renovate configuration — it has more moving parts (Gitea token, self-hosted runner access, endpoint config) and should not delay this security bump.

## Decision Queue — Open Items Requiring Human Judgment _Consolidated from the multi-persona review. Each item needs a decision before this issue can be fully closed. Items are grouped by theme._ --- ### Theme 1: `BODY_SIZE_LIMIT` — What value, and where? Raised by: Nora (Security), Tobias (DevOps), Leonie (UX) **The problem:** Patching the GHSA-2crg-3p73-43xp bypass means the adapter's `BODY_SIZE_LIMIT` will be _enforced_ for the first time. The current default is **512 KB**, which will reject every normal PDF upload. This limit must be raised _before_ deploying the patched adapter, not after. **What needs deciding:** 1. **What is the maximum document size this system should accept?** Historical Kurrent/Sütterlin documents at 300 DPI scan to 500 KB–15 MB as PDF. A practical ceiling of 50 MB covers multi-page originals without being reckless. 2. **Who sets the limit?** It needs to be set in two coordinated places: - `docker-compose.yml`: `BODY_SIZE_LIMIT=50M` under `frontend.environment` - Caddy reverse proxy `client_max_body_size` (not yet in repo — needs to be present before production go-live) 3. **Does the 413 error surface correctly in the UI?** If the adapter rejects the body before SvelteKit's form action runs, the `GlobalExceptionHandler` on the Spring Boot side is never invoked. The upload route (`/documents/new/`) may show a raw 413 rather than a localized error. This needs a quick manual test after the limit is set. **Recommendation from the review panel (non-binding):** Set `BODY_SIZE_LIMIT=50M` in `docker-compose.yml` as part of this PR, and create a follow-up issue to test the 413 UX path. --- ### Theme 2: Scope of this issue — bump only, or also CI gate + Renovate? Raised by: Elicit (Requirements), Sara (QA), Tobias (DevOps), Nora (Security) **The problem:** All four personas independently recommend adding `npm audit --audit-level=high --omit=dev` as a CI gate and fixing `renovate.json` for Gitea. These are the systemic fixes that prevent this class of issue from recurring. They are currently _not_ in scope for this issue. **What needs deciding:** Should this issue's scope expand to include: - [ ] Adding `npm audit --audit-level=high --omit=dev` to `.gitea/workflows/ci.yml` (15-minute task) - [ ] Fixing `renovate.json` with Gitea platform config and patch automerge (30-minute task) Or should these become **separate issues** that are created and prioritized alongside this one? **Recommendation from the review panel:** Include the CI audit gate in this PR (it is a one-liner with no risk). Create a separate issue for Renovate configuration — it has more moving parts (Gitea token, self-hosted runner access, endpoint config) and should not delay this security bump.
Sign in to join this conversation.
No Label P1-high security
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marcel/familienarchiv#458