From 32cc8ca0aa68c268faaf5590ab422f5cefe52c90 Mon Sep 17 00:00:00 2001 From: timonrieger Date: Wed, 29 Apr 2026 22:53:44 +0200 Subject: [PATCH] fix(server): replace email-in-use messages to prevent user-existence oracle Error messages on registration and profile-update that named whether an email address was already taken allowed callers to enumerate registered accounts. All three sites now return the same generic message regardless of whether the address is in use. --- e2e/src/specs/server/api/user.e2e-spec.ts | 2 +- server/src/services/base.service.ts | 2 +- server/src/services/user-admin.service.ts | 2 +- server/src/services/user.service.ts | 2 +- server/test/medium/specs/services/user.service.spec.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/e2e/src/specs/server/api/user.e2e-spec.ts b/e2e/src/specs/server/api/user.e2e-spec.ts index ee13a29c1b..7623cb5a63 100644 --- a/e2e/src/specs/server/api/user.e2e-spec.ts +++ b/e2e/src/specs/server/api/user.e2e-spec.ts @@ -120,7 +120,7 @@ describe('/users', () => { .set('Authorization', `Bearer ${nonAdmin.accessToken}`); expect(status).toBe(400); - expect(body).toMatchObject(errorDto.badRequest('Email already in use by another account')); + expect(body).toMatchObject(errorDto.badRequest('Email is not available')); }); it('should update my email', async () => { diff --git a/server/src/services/base.service.ts b/server/src/services/base.service.ts index dc402592cd..12e4278ad7 100644 --- a/server/src/services/base.service.ts +++ b/server/src/services/base.service.ts @@ -218,7 +218,7 @@ export class BaseService { async createUser(dto: Insertable & { email: string }): Promise { const exists = await this.userRepository.getByEmail(dto.email); if (exists) { - throw new BadRequestException('User exists'); + throw new BadRequestException('Email is not available'); } if (!dto.isAdmin) { diff --git a/server/src/services/user-admin.service.ts b/server/src/services/user-admin.service.ts index 58b4221cc9..4cdc26668d 100644 --- a/server/src/services/user-admin.service.ts +++ b/server/src/services/user-admin.service.ts @@ -64,7 +64,7 @@ export class UserAdminService extends BaseService { if (dto.email) { const duplicate = await this.userRepository.getByEmail(dto.email); if (duplicate && duplicate.id !== id) { - throw new BadRequestException('Email already in use by another account'); + throw new BadRequestException('Email is not available'); } } diff --git a/server/src/services/user.service.ts b/server/src/services/user.service.ts index d54f3a17ff..3627fe1096 100644 --- a/server/src/services/user.service.ts +++ b/server/src/services/user.service.ts @@ -49,7 +49,7 @@ export class UserService extends BaseService { if (dto.email) { const duplicate = await this.userRepository.getByEmail(dto.email); if (duplicate && duplicate.id !== user.id) { - throw new BadRequestException('Email already in use by another account'); + throw new BadRequestException('Email is not available'); } } diff --git a/server/test/medium/specs/services/user.service.spec.ts b/server/test/medium/specs/services/user.service.spec.ts index 2250034eea..c8c990a8da 100644 --- a/server/test/medium/specs/services/user.service.spec.ts +++ b/server/test/medium/specs/services/user.service.spec.ts @@ -48,7 +48,7 @@ describe(UserService.name, () => { ctx.getMock(EventRepository).emit.mockResolvedValue(); const user = mediumFactory.userInsert(); await expect(sut.createUser({ name: 'Test', email: user.email })).resolves.toMatchObject({ email: user.email }); - await expect(sut.createUser({ name: 'Test', email: user.email })).rejects.toThrow('User exists'); + await expect(sut.createUser({ name: 'Test', email: user.email })).rejects.toThrow('Email is not available'); }); it('should not return password', async () => {