From 519e485bc66349d03dae953fd7bb1e389116d17d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 20 Sep 2026 06:09:57 +0000 Subject: [PATCH] fix(root): resolve high @faker-js/faker vulnerability fixes NV-8815 Resolve GHSA-qxc2-j82w-r537: @faker-js/faker helpers.fake exploitable into arbitrary code execution (high). Vulnerable in <=10.4.0; patched in 10.5.0 (advisory lists 10.4.1 but npm only publishes 10.5.0+). Strategy A - direct dependency update. Bump the direct devDep in the five workspaces that use it: - apps/api ^6.0.0 -> ^10.5.0 - apps/worker ^6.0.0 -> ^10.5.0 - apps/dashboard ^9.5.0 -> ^10.5.0 - libs/dal ^6.0.0 -> ^10.5.0 - libs/testing ^6.0.0 -> ^10.5.0 faker v8 renamed faker.name -> faker.person and v10 removed the deprecated aliases, so mechanical renames applied across specs and test utilities: - faker.name.{firstName,lastName,jobTitle} -> faker.person.$1 - faker.datatype.uuid -> faker.string.uuid - faker.phone.phoneNumber -> faker.phone.number - faker.company.companyName -> faker.company.name Other faker APIs used in-tree (internet.*, image.avatar, lorem.words, commerce.productDescription) are unchanged from v6 through v10. Usage is confined to spec files and Playwright/testing helpers - no production runtime consumes faker. Advisory: https://github.com/advisories/GHSA-qxc2-j82w-r537 --- .../encrypt-api-keys-migration.spec.ts | 4 +-- apps/api/package.json | 2 +- .../unit/update-subscriber-channel.spec.ts | 6 ++-- apps/dashboard/package.json | 2 +- .../tests/utils/environment-service.ts | 2 +- apps/worker/package.json | 2 +- .../workflow/services/standard.worker.spec.ts | 6 ++-- libs/dal/package.json | 2 +- libs/testing/package.json | 2 +- libs/testing/src/environment.service.ts | 2 +- .../src/notification-template.service.ts | 4 +-- libs/testing/src/organization.service.ts | 4 +-- libs/testing/src/subscribers.service.ts | 6 ++-- libs/testing/src/user.service.ts | 8 ++--- libs/testing/src/user.session.ts | 6 ++-- libs/testing/src/workflow-override.service.ts | 2 +- pnpm-lock.yaml | 35 ++++++++----------- 17 files changed, 44 insertions(+), 51 deletions(-) diff --git a/apps/api/migrations/encrypt-api-keys/encrypt-api-keys-migration.spec.ts b/apps/api/migrations/encrypt-api-keys/encrypt-api-keys-migration.spec.ts index 372bdcc4cdf..f1512ef147f 100644 --- a/apps/api/migrations/encrypt-api-keys/encrypt-api-keys-migration.spec.ts +++ b/apps/api/migrations/encrypt-api-keys/encrypt-api-keys-migration.spec.ts @@ -31,7 +31,7 @@ describe('Encrypt Old api keys', () => { for (let i = 0; i < 2; i += 1) { await environmentRepository.create({ identifier: 'identifier' + i, - name: faker.name.jobTitle(), + name: faker.person.jobTitle(), _organizationId: session.organization._id, apiKeys: [ { @@ -84,7 +84,7 @@ describe('Encrypt Old api keys', () => { for (let i = 0; i < 2; i += 1) { await environmentRepository.create({ identifier: 'identifier' + i, - name: faker.name.jobTitle(), + name: faker.person.jobTitle(), _organizationId: session.organization._id, apiKeys: [ { diff --git a/apps/api/package.json b/apps/api/package.json index 9c80202f868..49e670068fd 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -151,7 +151,7 @@ "zod-to-json-schema": "^3.25.2" }, "devDependencies": { - "@faker-js/faker": "^6.0.0", + "@faker-js/faker": "^10.5.0", "@nestjs/cli": "11.0.23", "@nestjs/schematics": "11.1.0", "@nestjs/testing": "11.1.27", diff --git a/apps/api/src/app/subscribers/unit/update-subscriber-channel.spec.ts b/apps/api/src/app/subscribers/unit/update-subscriber-channel.spec.ts index a8c98129f3a..0149a0b97ae 100644 --- a/apps/api/src/app/subscribers/unit/update-subscriber-channel.spec.ts +++ b/apps/api/src/app/subscribers/unit/update-subscriber-channel.spec.ts @@ -425,10 +425,10 @@ describe('Update Subscriber channel credentials', () => { it('should update deviceTokens without duplication on channel creation (addChannelToSubscriber)', async () => { const subscriberId = SubscriberRepository.createObjectId(); const test = await subscriberRepository.create({ - firstName: faker.name.firstName(), - lastName: faker.name.lastName(), + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), email: faker.internet.email(), - phone: faker.phone.phoneNumber(), + phone: faker.phone.number(), _environmentId: session.environment._id, _organizationId: session.organization._id, subscriberId, diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json index 35f2e44a2d9..bd10b1e469f 100644 --- a/apps/dashboard/package.json +++ b/apps/dashboard/package.json @@ -166,7 +166,7 @@ "@clerk/backend": "^3.4.11", "@clerk/shared": "^4.23.0", "@clerk/testing": "^2.0.31", - "@faker-js/faker": "^9.5.0", + "@faker-js/faker": "^10.5.0", "@hookform/devtools": "^4.3.0", "@novu/dal": "workspace:*", "@novu/ee-auth": "workspace:*", diff --git a/apps/dashboard/tests/utils/environment-service.ts b/apps/dashboard/tests/utils/environment-service.ts index 8e216be4f8a..2873a07eb05 100644 --- a/apps/dashboard/tests/utils/environment-service.ts +++ b/apps/dashboard/tests/utils/environment-service.ts @@ -18,7 +18,7 @@ export class EnvironmentService { return await environmentRepository.create({ identifier: faker.string.uuid(), - name: name ?? faker.name.jobTitle(), + name: name ?? faker.person.jobTitle(), _organizationId: organizationId, ...(parentId && { _parentId: parentId }), apiKeys: [ diff --git a/apps/worker/package.json b/apps/worker/package.json index 8a2c0cbc436..e29bbb9adad 100644 --- a/apps/worker/package.json +++ b/apps/worker/package.json @@ -70,7 +70,7 @@ "uuid": "^11.1.1" }, "devDependencies": { - "@faker-js/faker": "^6.0.0", + "@faker-js/faker": "^10.5.0", "@nestjs/cli": "11.0.23", "@nestjs/schematics": "11.1.0", "@nestjs/testing": "11.1.27", diff --git a/apps/worker/src/app/workflow/services/standard.worker.spec.ts b/apps/worker/src/app/workflow/services/standard.worker.spec.ts index ca8a68c8d78..cde5feb546d 100644 --- a/apps/worker/src/app/workflow/services/standard.worker.spec.ts +++ b/apps/worker/src/app/workflow/services/standard.worker.spec.ts @@ -102,13 +102,13 @@ describe('Standard Worker', () => { const userService = new UserService(); const card = { - firstName: faker.name.firstName(), - lastName: faker.name.lastName(), + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), }; const userEntity: Partial = { lastName: card.lastName, firstName: card.firstName, - email: `${card.firstName}_${card.lastName}_${faker.datatype.uuid()}@gmail.com`.toLowerCase(), + email: `${card.firstName}_${card.lastName}_${faker.string.uuid()}@gmail.com`.toLowerCase(), profilePicture: `https://randomuser.me/api/portraits/men/${Math.floor(Math.random() * 60) + 1}.jpg`, tokens: [], password: 'asd#Faf4fd', diff --git a/libs/dal/package.json b/libs/dal/package.json index c15ce7ac372..4df123615c5 100644 --- a/libs/dal/package.json +++ b/libs/dal/package.json @@ -26,7 +26,7 @@ "dependencies": { "@aws-sdk/client-s3": "^3.382.0", "@aws-sdk/s3-request-presigner": "^3.382.0", - "@faker-js/faker": "^6.0.0", + "@faker-js/faker": "^10.5.0", "@novu/shared": "workspace:*", "class-transformer": "0.5.1", "cross-fetch": "^3.0.4", diff --git a/libs/testing/package.json b/libs/testing/package.json index a174db224a1..3155f24b732 100644 --- a/libs/testing/package.json +++ b/libs/testing/package.json @@ -23,7 +23,7 @@ "dependencies": { "@clerk/backend": "^3.4.11", "@clerk/shared": "^4.12.2", - "@faker-js/faker": "^6.0.0", + "@faker-js/faker": "^10.5.0", "@novu/dal": "workspace:*", "@novu/shared": "workspace:*", "JSONStream": "^1.3.5", diff --git a/libs/testing/src/environment.service.ts b/libs/testing/src/environment.service.ts index 5b2abe45cdc..e56d86e1bf3 100644 --- a/libs/testing/src/environment.service.ts +++ b/libs/testing/src/environment.service.ts @@ -23,7 +23,7 @@ export class EnvironmentService { return await this.environmentRepository.create({ identifier: uuid(), - name: name ?? faker.name.jobTitle(), + name: name ?? faker.person.jobTitle(), _organizationId: organizationId, ...(parentId && { _parentId: parentId }), apiKeys: [ diff --git a/libs/testing/src/notification-template.service.ts b/libs/testing/src/notification-template.service.ts index df3c57660e6..b1cf24cf1c7 100644 --- a/libs/testing/src/notification-template.service.ts +++ b/libs/testing/src/notification-template.service.ts @@ -162,7 +162,7 @@ export class NotificationTemplateService { const data = { _notificationGroupId: override.noGroupId ? undefined : groups[0]._id, _environmentId: this.environmentId, - name: override.name ?? faker.name.jobTitle(), + name: override.name ?? faker.person.jobTitle(), _organizationId: this.organizationId, _creatorId: this.userId, active: true, @@ -172,7 +172,7 @@ export class NotificationTemplateService { description: faker.commerce.productDescription().slice(0, 90), triggers: override.triggers ?? [ { - identifier: `test-event-${faker.datatype.uuid()}`, + identifier: `test-event-${faker.string.uuid()}`, type: 'event', variables: [{ name: 'firstName' }, { name: 'lastName' }, { name: 'urlVariable' }], }, diff --git a/libs/testing/src/organization.service.ts b/libs/testing/src/organization.service.ts index 2208cd1ceb3..e52bc09122d 100644 --- a/libs/testing/src/organization.service.ts +++ b/libs/testing/src/organization.service.ts @@ -10,14 +10,14 @@ export class OrganizationService { if (options) { return await this.organizationRepository.create({ logo: faker.image.avatar(), - name: faker.company.companyName(), + name: faker.company.name(), ...options, }); } return await this.organizationRepository.create({ logo: faker.image.avatar(), - name: faker.company.companyName(), + name: faker.company.name(), }); } diff --git a/libs/testing/src/subscribers.service.ts b/libs/testing/src/subscribers.service.ts index 212058ea897..ceb8ff37c8b 100644 --- a/libs/testing/src/subscribers.service.ts +++ b/libs/testing/src/subscribers.service.ts @@ -37,10 +37,10 @@ export class SubscribersService { } return await this.subscriberRepository.create({ - lastName: faker.name.lastName(), - firstName: faker.name.firstName(), + lastName: faker.person.lastName(), + firstName: faker.person.firstName(), email: faker.internet.email(), - phone: faker.phone.phoneNumber(), + phone: faker.phone.number(), _environmentId: this._environmentId, _organizationId: this._organizationId, subscriberId: SubscriberRepository.createObjectId(), diff --git a/libs/testing/src/user.service.ts b/libs/testing/src/user.service.ts index 951d426dc25..255b9813b3c 100644 --- a/libs/testing/src/user.service.ts +++ b/libs/testing/src/user.service.ts @@ -14,8 +14,8 @@ export class UserService { async createTestUser(): Promise { const user = await this.createUser({ email: this.randomEmail(), - firstName: faker.name.firstName(), - lastName: faker.name.lastName(), + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), password: this.testPassword(), }); @@ -34,8 +34,8 @@ export class UserService { const user = await this.userRepository.create({ email: normalizeEmail(userEntity?.email ?? faker.internet.email()), - firstName: userEntity?.firstName ?? faker.name.firstName(), - lastName: userEntity?.lastName ?? faker.name.lastName(), + firstName: userEntity?.firstName ?? faker.person.firstName(), + lastName: userEntity?.lastName ?? faker.person.lastName(), password: passwordHash, profilePicture: `https://randomuser.me/api/portraits/men/${Math.floor(Math.random() * 60) + 1}.jpg`, tokens: [], diff --git a/libs/testing/src/user.session.ts b/libs/testing/src/user.session.ts index 41fa8dfe1ef..7cadad1a423 100644 --- a/libs/testing/src/user.session.ts +++ b/libs/testing/src/user.session.ts @@ -108,15 +108,15 @@ export class UserSession { private async initializeCommunity(options: UserSessionOptions = {}) { const card = { - firstName: faker.name.firstName(), - lastName: faker.name.lastName(), + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), }; const userService = new UserService(); const userEntity: Partial = { lastName: card.lastName, firstName: card.firstName, - email: `${card.firstName}_${card.lastName}_${faker.datatype.uuid()}@gmail.com`.toLowerCase(), + email: `${card.firstName}_${card.lastName}_${faker.string.uuid()}@gmail.com`.toLowerCase(), profilePicture: `https://randomuser.me/api/portraits/men/${Math.floor(Math.random() * 60) + 1}.jpg`, tokens: [], password: TEST_USER_PASSWORD, diff --git a/libs/testing/src/workflow-override.service.ts b/libs/testing/src/workflow-override.service.ts index 2402584738c..8739a98b4bb 100644 --- a/libs/testing/src/workflow-override.service.ts +++ b/libs/testing/src/workflow-override.service.ts @@ -21,7 +21,7 @@ export class WorkflowOverrideService { const tenant = await this.tenantRepository.create({ _organizationId: organizationId, _environmentId: environmentId, - identifier: faker.datatype.uuid(), + identifier: faker.string.uuid(), name: 'name_123', data: { test1: 'test value1', test2: 'test value2' }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8dd977720bf..ff6292d2a81 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -678,8 +678,8 @@ importers: version: 3.25.2(zod@3.25.20) devDependencies: '@faker-js/faker': - specifier: ^6.0.0 - version: 6.3.1 + specifier: ^10.5.0 + version: 10.6.0 '@nestjs/cli': specifier: 11.0.23 version: 11.0.23(@swc/cli@0.3.12(@swc/core@1.7.26(@swc/helpers@0.5.23))(chokidar@4.0.3))(@swc/core@1.7.26(@swc/helpers@0.5.23))(@types/node@22.15.13)(prettier@3.3.3) @@ -1193,8 +1193,8 @@ importers: specifier: ^2.0.31 version: 2.0.31(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@faker-js/faker': - specifier: ^9.5.0 - version: 9.5.0 + specifier: ^10.5.0 + version: 10.6.0 '@hookform/devtools': specifier: ^4.3.0 version: 4.3.1(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -1694,8 +1694,8 @@ importers: version: 11.1.1 devDependencies: '@faker-js/faker': - specifier: ^6.0.0 - version: 6.3.1 + specifier: ^10.5.0 + version: 10.6.0 '@nestjs/cli': specifier: 11.0.23 version: 11.0.23(@swc/cli@0.3.12(@swc/core@1.7.26(@swc/helpers@0.5.23))(chokidar@4.0.3))(@swc/core@1.7.26(@swc/helpers@0.5.23))(@types/node@22.15.13)(prettier@3.7.4) @@ -2956,8 +2956,8 @@ importers: specifier: ^3.382.0 version: 3.575.0 '@faker-js/faker': - specifier: ^6.0.0 - version: 6.3.1 + specifier: ^10.5.0 + version: 10.6.0 '@nestjs/common': specifier: 11.1.27 version: 11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) @@ -3344,8 +3344,8 @@ importers: specifier: ^4.12.2 version: 4.12.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@faker-js/faker': - specifier: ^6.0.0 - version: 6.3.1 + specifier: ^10.5.0 + version: 10.6.0 '@novu/dal': specifier: workspace:* version: link:../dal @@ -8109,14 +8109,9 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@faker-js/faker@6.3.1': - resolution: {integrity: sha512-8YXBE2ZcU/pImVOHX7MWrSR/X5up7t6rPWZlk34RwZEcdr3ua6X+32pSd6XuOQRN+vbuvYNfA6iey8NbrjuMFQ==} - engines: {node: '>=14.0.0', npm: '>=6.0.0'} - - '@faker-js/faker@9.5.0': - resolution: {integrity: sha512-3qbjLv+fzuuCg3umxc9/7YjrEXNaKwHgmig949nfyaTx8eL4FAsvFbu+1JcFUj1YAXofhaDn6JdEUBTYuk0Ssw==} - engines: {node: '>=18.0.0', npm: '>=9.0.0'} - deprecated: Please update to a newer version + '@faker-js/faker@10.6.0': + resolution: {integrity: sha512-3RQHgEtvL1Frl/d1cSreo7qhJ3Gk1OdNUai/CtZ8G+wYeRQnJih3s9xJ9/kgYekPQRdwgh0HXRPqMlzWGwivIQ==} + engines: {node: ^20.19.0 || ^22.13.0 || ^23.5.0 || >=24.0.0, npm: '>=10'} '@fastify/busboy@3.1.1': resolution: {integrity: sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==} @@ -35762,9 +35757,7 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 - '@faker-js/faker@6.3.1': {} - - '@faker-js/faker@9.5.0': {} + '@faker-js/faker@10.6.0': {} '@fastify/busboy@3.1.1': {}