Fix upload path-traversal RCE vector, patch all known-vulnerable deps
Path traversal (CWE-22/CWE-73): event-image, branding (logo/favicon), and event-attachment uploads built the saved filename from the client-supplied original filename with no sanitization, and multer's diskStorage joins that straight into the destination path. A crafted filename containing `../` sequences could write the uploaded file anywhere the server process has write access — reachable by any supervisor-level account, and briefly pre-auth via the branding uploads during initial /setup. Filenames are now always server- generated (random bytes + validated extension); the original name is kept only as display metadata. Dependencies: express-rate-limit was declared only at the repo root despite being required directly by backend/src/index.js, so a plain `cd backend && npm install` (per the deployment doc) would never install it — moved it into backend/package.json. Bumped next off a version affected by a critical unauthenticated RCE (React Flight protocol) and switched it from an exact pin to a caret range so future patches install automatically. Bumped multer/nodemailer/jsonwebtoken/ uuid to patched versions, with an override forcing the vulnerable nested uuid inside exceljs and the vulnerable postcss bundled inside next to the patched versions too. `npm audit` is now clean (0 vulnerabilities) across root, backend, and frontend. Hardening: jwt.verify() now pins algorithms: ['HS256'] instead of trusting the token header; /uploads now serves with a restrictive CSP and X-Content-Type-Options: nosniff so an uploaded SVG containing <script> can't execute if opened directly. Verified: backend's Jest suite passes, the backend boots and serves real requests on the bumped deps, and `next build` compiles/type- checks cleanly on the bumped frontend deps. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSWFWQsjTc9GyffPiXEDQT
This commit is contained in:
@@ -7,6 +7,15 @@ and this project follows [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Security
|
||||
|
||||
- Fixed a path-traversal vulnerability in event-image, branding (logo/favicon), and event-attachment uploads: the stored filename embedded the client-supplied `originalname` unsanitized, so a crafted filename (e.g. containing `../`) could write the uploaded file outside the intended `public/uploads` subfolder anywhere the server process could write. Uploaded files are now always saved under a server-generated random name; the original filename is preserved only as display metadata.
|
||||
- `express-rate-limit` was declared as a root-only dependency despite being required directly by the backend (`backend/src/index.js`) — a plain `cd backend && npm install`, as documented in the deployment guide, would not have installed it. It's now a proper `backend/package.json` dependency.
|
||||
- Bumped `next` (frontend) off a version affected by a critical unauthenticated RCE in the React Flight protocol (GHSA-9qr9-h5gf-34mp) and several other CVEs, and switched it from an exact pin to `^15.5.24` so future patch releases install automatically.
|
||||
- Bumped `multer`, `nodemailer`, `jsonwebtoken`, and `uuid` (backend) to versions fixing DoS, SMTP/CRLF-injection, HMAC-verification, and buffer-bounds advisories; added an `overrides` entry so the vulnerable `uuid` nested under `exceljs` is also patched. Ran `npm audit fix` across all three workspaces (root/backend/frontend) — 0 known vulnerabilities remain.
|
||||
- `jwt.verify()` now pins `algorithms: ['HS256']` explicitly rather than trusting the algorithm from the token header.
|
||||
- Uploaded assets served from `/uploads` now get `Content-Security-Policy: default-src 'none'; sandbox` and `X-Content-Type-Options: nosniff`, so an uploaded SVG containing a `<script>` can no longer execute if opened directly.
|
||||
|
||||
## [1.10.0] - 2026-08-28
|
||||
|
||||
### Added
|
||||
|
||||
Reference in New Issue
Block a user