- nodemailer 8 -> 9 (GHSA-p6gq-j5cr-w38f, raw-option file-read/SSRF; we
never use the raw option — notificationDelivery tests 13/13)
- xlsx -> official SheetJS dist 0.20.3 (prototype pollution
GHSA-4r6h-8v6p-xvw6 + ReDoS GHSA-5pgg-2g8v-p4x9; npm registry line is
abandoned at 0.18.5 with no fix). API-identical for our 8 call sites;
import/export round-trip tests green. NOTE: the lockfile now pins
https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz — CI runners and
Docker builds need egress to cdn.sheetjs.com
- CI: npm audit --audit-level critical -> high (0 vulns as of this
commit; highs can no longer pass silently — QA-B0-02)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- CI now runs gitleaks (secret scanning, .gitleaks.toml allowlists
fixtures/data/generated) and `npm audit --audit-level=critical`.
- SECURITY.md: disclosure policy, the controls in place, operational
hardening, and the two assessed HIGH audit exceptions (nodemailer `raw`
unused → not exploitable; xlsx confined to import w/ raw:false + limits).
- tests/securityCoverage.test.js: static invariant that every non-public
router mount carries requireAuth (+ CSRF for authed, requireAdmin for
admin) — a new unprotected route now fails CI. 4 tests; suite 236/236.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pillar A enforcement so standards can't drift:
- .forgejo CI now runs format:check + lint (client+server) + typecheck
(client) + typecheck:server, in addition to the existing check:server /
tests / build. Previously lint and typecheck were NOT run in CI.
- lefthook pre-commit auto-formats staged files (prettier) + lints;
pre-push typechecks. Auto-installed via the `prepare` script.
- Knip config (advisory `npm run knip`) for dead-code/unused-export
review; the design-system ui/** is ignored to keep signal clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>