From eb21092f4611cb4be50b29add03b97cb1a3fa5f2 Mon Sep 17 00:00:00 2001 From: oxmc7769 Date: Sun, 5 Jul 2026 06:16:19 -0700 Subject: [PATCH] chore: resolve remaining audit vulnerabilities (uuid, @types/request, brace-expansion) - Removed @types/request (unused devDependency, no "request" import anywhere in the codebase) - it was the actual source of the critical form-data vulnerability via its own outdated nested dependency. - Bumped uuid v3 -> v11 (patched version) across all 8 call sites, migrating from the old default-import "uuid.v4()"/"uuid()" style to the named-export "v4 as uuidv4" style the new major requires. Tried v14 first - it broke the Jest test suite entirely (ships ESM-only, Node's CJS require() choked on it) - v11 is the oldest patched version that still works under Jest/CJS. Removed 2 more unused "import uuid" lines with no actual usage. - Picked up brace-expansion via a follow-up non-breaking npm audit fix. Verified full build (frontend+backend) and full test suite (179 tests) after each step. 45 -> 4 unique vulnerable packages remaining: aws-sdk (its own advisory, "fix" would downgrade it - not worth it), aws-sdk's own nested uuid (same reason), esbuild/vite (major version bump to vite 8, needs its own dedicated upgrade pass), and nodemailer (breaking API change, only exercised when EMAIL_VERIFICATION is enabled) - all left for a deliberate separate decision rather than forced through here. --- .../services/chunk-service/chunk-service.ts | 1 - .../utils/createImageThumbnail.ts | 4 +- .../utils/createVideoThumbnail.ts | 4 +- .../chunk-service/utils/getBusboyData.ts | 4 +- .../utils/getFolderUploadBusboyData.ts | 4 +- .../utils/tempCreateVideoThumbnail.ts | 4 +- package-lock.json | 80 +++++-------------- package.json | 5 +- src/axiosInterceptor/index.ts | 6 +- src/hooks/files.ts | 6 +- src/hooks/user.ts | 4 +- src/routers/AppRouter.jsx | 1 - 12 files changed, 41 insertions(+), 82 deletions(-) diff --git a/backend/services/chunk-service/chunk-service.ts b/backend/services/chunk-service/chunk-service.ts index 3e749fe..6d179d9 100644 --- a/backend/services/chunk-service/chunk-service.ts +++ b/backend/services/chunk-service/chunk-service.ts @@ -5,7 +5,6 @@ import NotFoundError from "../../utils/NotFoundError"; import crypto from "crypto"; import uploadFileToStorage from "./utils/getBusboyData"; import videoChecker from "../../utils/videoChecker"; -import uuid from "uuid"; import { FileInterface, FileMetadateInterface } from "../../models/file-model"; import { getFileDB, diff --git a/backend/services/chunk-service/utils/createImageThumbnail.ts b/backend/services/chunk-service/utils/createImageThumbnail.ts index e4b1c34..f7c0e8c 100644 --- a/backend/services/chunk-service/utils/createImageThumbnail.ts +++ b/backend/services/chunk-service/utils/createImageThumbnail.ts @@ -2,7 +2,7 @@ import crypto from "crypto"; import sharp from "sharp"; import { FileInterface } from "../../../models/file-model"; import { UserInterface } from "../../../models/user-model"; -import uuid from "uuid"; +import { v4 as uuidv4 } from "uuid"; import env from "../../../enviroment/env"; import { createGenericParams } from "./storageHelper"; import { S3Actions } from "../actions/S3-actions"; @@ -29,7 +29,7 @@ const processData = ( let CIPHER_KEY = crypto.createHash("sha256").update(password!).digest(); - const thumbnailFilename = uuid.v4(); + const thumbnailFilename = uuidv4(); const thumbnailIV = crypto.randomBytes(16); diff --git a/backend/services/chunk-service/utils/createVideoThumbnail.ts b/backend/services/chunk-service/utils/createVideoThumbnail.ts index b5ea624..71965eb 100644 --- a/backend/services/chunk-service/utils/createVideoThumbnail.ts +++ b/backend/services/chunk-service/utils/createVideoThumbnail.ts @@ -3,7 +3,7 @@ import sharp from "sharp"; import { FileInterface } from "../../../models/file-model"; import { UserInterface } from "../../../models/user-model"; import fs from "fs"; -import uuid from "uuid"; +import { v4 as uuidv4 } from "uuid"; import env from "../../../enviroment/env"; import ffmpeg from "fluent-ffmpeg"; import tempCreateVideoThumbnail from "./tempCreateVideoThumbnail"; @@ -44,7 +44,7 @@ const createVideoThumbnail = ( let CIPHER_KEY = crypto.createHash("sha256").update(password!).digest(); - const thumbnailFilename = uuid.v4(); + const thumbnailFilename = uuidv4(); const readStreamParams = createGenericParams({ filePath: file.metadata.filePath, diff --git a/backend/services/chunk-service/utils/getBusboyData.ts b/backend/services/chunk-service/utils/getBusboyData.ts index d5beb0f..2621f52 100644 --- a/backend/services/chunk-service/utils/getBusboyData.ts +++ b/backend/services/chunk-service/utils/getBusboyData.ts @@ -1,7 +1,7 @@ import { EventEmitter, Stream } from "stream"; import { UserInterface } from "../../../models/user-model"; import { FileInterface, FileMetadateInterface } from "../../../models/file-model"; -import uuid from "uuid"; +import { v4 as uuidv4 } from "uuid"; import crypto from "crypto"; import ForbiddenError from "../../../utils/ForbiddenError"; import env from "../../../enviroment/env"; @@ -81,7 +81,7 @@ const processData = ( const uploadFile = (filename: string, fileStream: Stream) => { return new Promise<{ filename: string; metadata: FileMetadateInterface }>( (resolve, reject) => { - const randomFilenameID = uuid.v4(); + const randomFilenameID = uuidv4(); const password = user.getEncryptionKey(); diff --git a/backend/services/chunk-service/utils/getFolderUploadBusboyData.ts b/backend/services/chunk-service/utils/getFolderUploadBusboyData.ts index 837faf4..442914d 100644 --- a/backend/services/chunk-service/utils/getFolderUploadBusboyData.ts +++ b/backend/services/chunk-service/utils/getFolderUploadBusboyData.ts @@ -1,5 +1,5 @@ import { Stream } from "stream"; -import uuid from "uuid"; +import { v4 as uuidv4 } from "uuid"; import { UserInterface } from "../../../models/user-model"; import { FileInterface, FileMetadateInterface } from "../../../models/file-model"; import env from "../../../enviroment/env"; @@ -100,7 +100,7 @@ const processData = ( const fileData = fileDataMap[index]; - const randomFilenameID = uuid.v4(); + const randomFilenameID = uuidv4(); const password = user.getEncryptionKey(); diff --git a/backend/services/chunk-service/utils/tempCreateVideoThumbnail.ts b/backend/services/chunk-service/utils/tempCreateVideoThumbnail.ts index ccf4764..a8edc7a 100644 --- a/backend/services/chunk-service/utils/tempCreateVideoThumbnail.ts +++ b/backend/services/chunk-service/utils/tempCreateVideoThumbnail.ts @@ -3,7 +3,7 @@ import sharp from "sharp"; import { FileInterface } from "../../../models/file-model"; import { UserInterface } from "../../../models/user-model"; import fs from "fs"; -import uuid from "uuid"; +import { v4 as uuidv4 } from "uuid"; import env from "../../../enviroment/env"; import ffmpeg from "fluent-ffmpeg"; import { S3Actions } from "../actions/S3-actions"; @@ -27,7 +27,7 @@ const tempCreateVideoThumbnail = ( let CIPHER_KEY = crypto.createHash("sha256").update(password!).digest(); - const thumbnailFilename = uuid.v4(); + const thumbnailFilename = uuidv4(); const readStreamParams = createGenericParams({ filePath: file.metadata.filePath, diff --git a/package-lock.json b/package-lock.json index 29b4cd8..6a881f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,7 +56,7 @@ "sharp": "^0.33.4", "sweetalert2": "^11.15.10", "temp": "^0.9.1", - "uuid": "^3.4.0", + "uuid": "^11.1.1", "validator": "^13.12.0" }, "devDependencies": { @@ -89,11 +89,10 @@ "@types/prompts": "^2.4.9", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@types/request": "^2.48.5", "@types/request-ip": "0.0.35", "@types/sharp": "^0.25.0", "@types/supertest": "^6.0.2", - "@types/uuid": "^7.0.2", + "@types/uuid": "^11.0.0", "@types/validator": "^13.0.0", "@vitejs/plugin-react": "^4.3.0", "autoprefixer": "^10.4.19", @@ -4678,13 +4677,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/caseless": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", - "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/compression": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.5.tgz", @@ -4975,19 +4967,6 @@ "@types/node": "*" } }, - "node_modules/@types/request": { - "version": "2.48.12", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz", - "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/caseless": "*", - "@types/node": "*", - "@types/tough-cookie": "*", - "form-data": "^2.5.0" - } - }, "node_modules/@types/request-ip": { "version": "0.0.35", "resolved": "https://registry.npmjs.org/@types/request-ip/-/request-ip-0.0.35.tgz", @@ -5086,13 +5065,6 @@ "@types/superagent": "^8.1.0" } }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", @@ -5107,11 +5079,15 @@ "license": "MIT" }, "node_modules/@types/uuid": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-7.0.8.tgz", - "integrity": "sha512-95N4tyM4B5u1sj2m8Tht09qWHju2ht413GBFz8CHtxp8aIiJUF6t51MsR7jC9OF4rRVf93AxE++WJe7+Puc1UA==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-11.0.0.tgz", + "integrity": "sha512-HVyk8nj2m+jcFRNazzqyVKiZezyhDKrGUA3jlEcg/nZ6Ms+qHwocba1Y/AaVaznJTAM9xpdFSh+ptbNrhOGvZA==", + "deprecated": "This is a stub types definition. uuid provides its own type definitions, so you do not need this installed.", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "uuid": "*" + } }, "node_modules/@types/validator": { "version": "13.12.2", @@ -6351,9 +6327,9 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -8754,23 +8730,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/form-data": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.3.tgz", - "integrity": "sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "mime-types": "^2.1.35", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/formidable": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.5.tgz", @@ -15688,13 +15647,16 @@ } }, "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", "bin": { - "uuid": "bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/v8-to-istanbul": { diff --git a/package.json b/package.json index e229f9a..a20249c 100755 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "sharp": "^0.33.4", "sweetalert2": "^11.15.10", "temp": "^0.9.1", - "uuid": "^3.4.0", + "uuid": "^11.1.1", "validator": "^13.12.0" }, "devDependencies": { @@ -101,11 +101,10 @@ "@types/prompts": "^2.4.9", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@types/request": "^2.48.5", "@types/request-ip": "0.0.35", "@types/sharp": "^0.25.0", "@types/supertest": "^6.0.2", - "@types/uuid": "^7.0.2", + "@types/uuid": "^11.0.0", "@types/validator": "^13.0.0", "@vitejs/plugin-react": "^4.3.0", "autoprefixer": "^10.4.19", diff --git a/src/axiosInterceptor/index.ts b/src/axiosInterceptor/index.ts index f27e7f2..d65f062 100644 --- a/src/axiosInterceptor/index.ts +++ b/src/axiosInterceptor/index.ts @@ -1,5 +1,5 @@ import axios from "axios"; -import uuid from "uuid"; +import { v4 as uuidv4 } from "uuid"; import getBackendURL from "../utils/getBackendURL"; let browserIDCheck = localStorage.getItem("browser-id"); @@ -19,7 +19,7 @@ const axios3 = axios.create({ baseURL: getBackendURL() }); axiosRetry.interceptors.request.use( (config) => { if (!browserIDCheck) { - browserIDCheck = uuid.v4(); + browserIDCheck = uuidv4(); localStorage.setItem("browser-id", browserIDCheck); } @@ -56,7 +56,7 @@ axiosRetry.interceptors.response.use( } if (!browserIDCheck) { - browserIDCheck = uuid.v4(); + browserIDCheck = uuidv4(); localStorage.setItem("browser-id", browserIDCheck); } diff --git a/src/hooks/files.ts b/src/hooks/files.ts index 0236557..e1c134f 100644 --- a/src/hooks/files.ts +++ b/src/hooks/files.ts @@ -14,7 +14,7 @@ import { import { useAppDispatch, useAppSelector } from "./store"; import { useUtils } from "./utils"; import { FileInterface } from "../types/file"; -import { v4 as uuid } from "uuid"; +import { v4 as uuidv4 } from "uuid"; import axiosNonInterceptor from "axios"; import { addFileUploadCancelToken, @@ -122,7 +122,7 @@ export const useUploader = () => { const parent = params.id || "/"; const currentFile = files[i]; - const currentID = uuid(); + const currentID = uuidv4(); const CancelToken = axiosNonInterceptor.CancelToken; const source = CancelToken.source(); @@ -243,7 +243,7 @@ export const useUploader = () => { cancelToken: source.token, }; - const currentID = uuid(); + const currentID = uuidv4(); dispatch( addUpload({ diff --git a/src/hooks/user.ts b/src/hooks/user.ts index f2a94d1..fd46fd2 100644 --- a/src/hooks/user.ts +++ b/src/hooks/user.ts @@ -1,11 +1,11 @@ import { useCallback, useEffect } from "react"; import { getAccessToken } from "../api/userAPI"; -import uuid from "uuid"; +import { v4 as uuidv4 } from "uuid"; const useAccessTokenHandler = () => { const refreshAccessToken = useCallback(async () => { try { - const browserID = localStorage.getItem("browser-id") || uuid.v4(); + const browserID = localStorage.getItem("browser-id") || uuidv4(); if (!localStorage.getItem("browser-id")) { localStorage.setItem("browser-id", browserID); } diff --git a/src/routers/AppRouter.jsx b/src/routers/AppRouter.jsx index 219686a..9ca6b73 100755 --- a/src/routers/AppRouter.jsx +++ b/src/routers/AppRouter.jsx @@ -12,7 +12,6 @@ import PrivateRoute from "./PrivateRoute"; import PublicRoute from "./PublicRoute"; import DownloadPage from "../components/DownloadPage/DownloadPage"; import VerifyEmailPage from "../components/VerifyEmailPage/VerifyEmailPage"; -import uuid from "uuid"; import ResetPasswordPage from "../components/ResetPasswordPage/ResetPasswordPage"; import SettingsPage from "../components/SettingsPage/SettingsPage"; import Homepage from "../components/Homepage/Homepage";