Fix all backend lint errors and security vulnerabilities

Backend lint (4 errors fixed):
- auth.ts: suppress @typescript-eslint/no-namespace on Express global
  augmentation (legitimate TS pattern for extending Request type)
- clients.ts: remove unnecessary \. escape in regex character class
- devices.ts: remove unnecessary \- escape by moving hyphen to front [-:]
- PollerService.ts: add comment to empty catch block

Security audit (high/critical CVEs fixed):
- frontend: bump axios (critical SSRF), lodash (high injection),
  follow-redirects (moderate) via npm audit fix
- backend: bump nodemailer 6.x → 8.0.5 (fixes 4 SMTP injection CVEs)
This commit is contained in:
2GT-Rich
2026-04-16 11:08:42 -07:00
parent 484e529b88
commit bd85f988da
7 changed files with 26 additions and 22 deletions
+4 -4
View File
@@ -20,7 +20,7 @@
"ioredis": "^5.3.2", "ioredis": "^5.3.2",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"morgan": "^1.10.0", "morgan": "^1.10.0",
"nodemailer": "^6.9.13", "nodemailer": "^8.0.5",
"pg": "^8.11.3", "pg": "^8.11.3",
"socket.io": "^4.6.1", "socket.io": "^4.6.1",
"ssh2": "^1.14.0", "ssh2": "^1.14.0",
@@ -3055,9 +3055,9 @@
} }
}, },
"node_modules/nodemailer": { "node_modules/nodemailer": {
"version": "6.10.1", "version": "8.0.5",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.1.tgz", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.5.tgz",
"integrity": "sha512-Z+iLaBGVaSjbIzQ4pX6XV41HrooLsQ10ZWPUehGmuantvzWoDVBnmsdUcOIDM1t+yPor5pDhVlDESgOMEGxhHA==", "integrity": "sha512-0PF8Yb1yZuQfQbq+5/pZJrtF6WQcjTd5/S4JOHs9PGFxuTqoB/icwuB44pOdURHJbRKX1PPoJZtY7R4VUoCC8w==",
"license": "MIT-0", "license": "MIT-0",
"engines": { "engines": {
"node": ">=6.0.0" "node": ">=6.0.0"
+1 -1
View File
@@ -23,7 +23,7 @@
"ioredis": "^5.3.2", "ioredis": "^5.3.2",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"morgan": "^1.10.0", "morgan": "^1.10.0",
"nodemailer": "^6.9.13", "nodemailer": "^8.0.5",
"pg": "^8.11.3", "pg": "^8.11.3",
"socket.io": "^4.6.1", "socket.io": "^4.6.1",
"ssh2": "^1.14.0", "ssh2": "^1.14.0",
+1
View File
@@ -8,6 +8,7 @@ export interface AuthPayload {
} }
declare global { declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Express { namespace Express {
interface Request { interface Request {
user?: AuthPayload; user?: AuthPayload;
+1 -1
View File
@@ -251,7 +251,7 @@ router.get('/:mac/signal', async (req: Request, res: Response) => {
// POST /api/clients/:mac/wol — send Wake-on-LAN magic packet // POST /api/clients/:mac/wol — send Wake-on-LAN magic packet
router.post('/:mac/wol', requireWrite, async (req: Request, res: Response) => { router.post('/:mac/wol', requireWrite, async (req: Request, res: Response) => {
const mac = req.params.mac.replace(/[^0-9a-fA-F:.-]/g, ''); const mac = req.params.mac.replace(/[^0-9a-fA-F:.-]/g, '');
const hexMac = mac.replace(/[:\-\.]/g, ''); const hexMac = mac.replace(/[:\-.]/g, '');
if (hexMac.length !== 12) { if (hexMac.length !== 12) {
return res.status(400).json({ error: 'Invalid MAC address' }); return res.status(400).json({ error: 'Invalid MAC address' });
} }
+1 -1
View File
@@ -1464,7 +1464,7 @@ router.post('/:id/tools/wol', requireWrite, async (req: Request, res: Response)
if (!iface) return res.status(400).json({ error: 'interface is required' }); if (!iface) return res.status(400).json({ error: 'interface is required' });
// Basic MAC validation // Basic MAC validation
if (!/^([0-9A-Fa-f]{2}[:\-]){5}[0-9A-Fa-f]{2}$/.test(mac)) { if (!/^([0-9A-Fa-f]{2}[-:]){5}[0-9A-Fa-f]{2}$/.test(mac)) {
return res.status(400).json({ error: 'Invalid MAC address format' }); return res.status(400).json({ error: 'Invalid MAC address format' });
} }
+1 -1
View File
@@ -299,7 +299,7 @@ export class PollerService {
try { try {
const { redis } = await import('../config/redis'); const { redis } = await import('../config/redis');
await redis.set(key, String(ts), 'EX', 600); await redis.set(key, String(ts), 'EX', 600);
} catch {} } catch { /* redis unavailable — timestamp not cached */ }
} }
private startWorkers(): void { private startWorkers(): void {
+17 -14
View File
@@ -2320,14 +2320,14 @@
} }
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.13.6", "version": "1.15.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz",
"integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", "integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.11", "follow-redirects": "^1.15.11",
"form-data": "^4.0.5", "form-data": "^4.0.5",
"proxy-from-env": "^1.1.0" "proxy-from-env": "^2.1.0"
} }
}, },
"node_modules/balanced-match": { "node_modules/balanced-match": {
@@ -3700,9 +3700,9 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/follow-redirects": { "node_modules/follow-redirects": {
"version": "1.15.11", "version": "1.16.0",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -4715,9 +4715,9 @@
} }
}, },
"node_modules/lodash": { "node_modules/lodash": {
"version": "4.17.23", "version": "4.18.1",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/lodash.merge": { "node_modules/lodash.merge": {
@@ -5371,10 +5371,13 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/proxy-from-env": { "node_modules/proxy-from-env": {
"version": "1.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
"license": "MIT" "license": "MIT",
"engines": {
"node": ">=10"
}
}, },
"node_modules/punycode": { "node_modules/punycode": {
"version": "2.3.1", "version": "2.3.1",