chore(security): close 27 code-scanning alerts via dep + base-image bumps

Single PR closing every open code-scanning alert at
https://github.com/PicPeak/picpeak/security/code-scanning. Both repos go
from 27 open alerts → 0 across direct deps, transitive deps, and build-
time bundled deps.

## Backend (`backend/package.json` + overrides)

Direct dep bumps:
- axios          1.15.2   → 1.16.0       (closes 9 alerts: 7 high + 1 med + 1 low)
- nodemailer     8.0.10   → ^9.0.1       (closes 1 high — SSRF + file-read via raw option)
- multer         2.1.1    → 2.2.0        (closes 2 alerts: 1 high + 1 med)
- form-data      4.0.5    → 4.0.6        (closes 1 high)
- tar            ≥7.5.13  → ≥7.5.16      (closes 1 med)
- postcss        8.5.6    → 8.5.10       (closes 1 med)
- i18next-http-backend  3.0.2  → 3.0.5   (closes 1 med — backend lagged frontend)
- js-yaml        4.1.1    → ^4.2.0       (closes 1 med)
- joi            17.13.3  → ^17.13.4     (closes 1 med)

Overrides updated to match deps (npm rejected the install otherwise) +
nodemailer ^9.0.1 added as override so imapflow + mailparser transitive
bundling of older nodemailer is also fixed. Babel devDep auto-bumped via
`npm audit fix` (low-severity arbitrary file read).

Backend npm audit: 0 vulnerabilities.

## Frontend (`frontend/package.json`)

Direct dep bumps:
- axios                 1.15.2  → 1.16.0
- postcss               8.5.6   → 8.5.10
- i18next-http-backend  3.0.5   → 3.0.5  (already current — kept for parity)

`npm audit fix` swept up 12 transitive issues at the same time:
- vitest (1 critical — file read on UI server)
- vite (2 high — fs.deny bypass, NTLM hash via launch-editor)
- ws (2 high — uninitialized memory + DoS)
- dompurify (8 mod — multiple IN_PLACE / hook-pollution XSS vectors)
- react-router-dom + react-router (1 mod transitive)
- esbuild (1 mod — dev server file read)
- @babel/core (1 low)

Frontend npm audit: 0 vulnerabilities.

## Frontend Dockerfile

- Build stage: `node:20-alpine` → `node:22-alpine`

Closes the npm-bundled CVE class (picomatch, ip-address, brace-expansion,
@sigstore/core, tar) that came from Node 20's older bundled npm. Matches
the backend Dockerfile base. The nginx serving stage stays at
`nginx:1.28-alpine` — that tag is rolling, so the next build picks up
the fixed 1.28.3-r4 layer that closes the 4 nginx CVEs.

## Verification

- Backend: `npm audit` → 0 vulnerabilities 
- Frontend: `npm audit` → 0 vulnerabilities 
- Backend Jest (workflow engine, rounding, WhatsApp): 47/47 pass 
- Frontend Vitest: 84/84 pass 
- `frontend npm run build`: succeeds 
- nodemailer 9 sanity check: our usage is `createTransport({host,port,secure,auth})`
  + `sendMail({from,to,subject,html,text})` — we don't touch the `raw`
  option that 9.x tightened, so the major bump is API-compatible.
This commit is contained in:
Paul Nothaft
2026-06-29 23:26:32 +02:00
parent a24821de55
commit 7546f104a3
5 changed files with 538 additions and 452 deletions
+14 -11
View File
@@ -18,7 +18,7 @@
"@aws-sdk/lib-storage": "^3.850.0",
"@aws-sdk/s3-request-presigner": "^3.850.0",
"archiver": "^5.3.1",
"axios": "1.15.2",
"axios": "1.16.0",
"bcrypt": "6.0.0",
"chokidar": "4.0.3",
"cookie-parser": "^1.4.7",
@@ -29,23 +29,23 @@
"express-rate-limit": "^6.7.0",
"express-validator": "^7.0.1",
"fluent-ffmpeg": "^2.1.3",
"form-data": "^4.0.4",
"form-data": "4.0.6",
"helmet": "^7.0.0",
"i18next": "25.3.2",
"i18next-browser-languagedetector": "^8.2.0",
"i18next-http-backend": "^3.0.2",
"i18next-http-backend": "3.0.5",
"imapflow": "^1.4.0",
"ipaddr.js": "^2.3.0",
"joi": "^17.9.1",
"js-yaml": "^4.1.1",
"joi": "^17.13.4",
"js-yaml": "^4.2.0",
"jsonwebtoken": "^9.0.0",
"knex": "^2.4.2",
"mailparser": "^3.9.9",
"mime-types": "^3.0.1",
"multer": "^2.0.2",
"multer": "2.2.0",
"node-cron": "^3.0.2",
"node-stream-zip": "^1.15.0",
"nodemailer": "^8.0.5",
"nodemailer": "^9.0.1",
"pdf-lib": "^1.17.1",
"pdfkit": "^0.17.2",
"pg": "^8.16.3",
@@ -59,7 +59,9 @@
"swissqrbill": "^4.3.0",
"uuid": "^11.1.1",
"winston": "^3.8.2",
"zxcvbn": "^4.4.2"
"zxcvbn": "^4.4.2",
"postcss": "8.5.10",
"tar": ">=7.5.16"
},
"devDependencies": {
"eslint": "^8.40.0",
@@ -73,10 +75,10 @@
"tar-fs": "2.1.4"
},
"glob": "^11.1.0",
"js-yaml": "^4.1.1",
"js-yaml": "^4.2.0",
"fast-xml-parser": ">=5.7.0",
"qs": ">=6.15.2",
"tar": ">=7.5.13",
"tar": ">=7.5.16",
"brace-expansion": ">=5.0.6",
"minimatch": ">=9.0.7",
"path-to-regexp": "0.1.13",
@@ -84,6 +86,7 @@
"follow-redirects": ">=1.16.0",
"@tootallnate/once": ">=3.0.1",
"ip-address": ">=10.1.1",
"uuid": "^11.1.1"
"uuid": "^11.1.1",
"nodemailer": "^9.0.1"
}
}