From facd3bd331e9e79e3036fda8171ed12ae17ee340 Mon Sep 17 00:00:00 2001 From: bo0tzz Date: Thu, 16 Apr 2026 15:06:55 +0200 Subject: [PATCH] fix: oauth issuerUrl validation (#27848) --- server/src/dtos/system-config.dto.ts | 7 ++++++- server/src/services/system-config.service.spec.ts | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/server/src/dtos/system-config.dto.ts b/server/src/dtos/system-config.dto.ts index b5222fd883..8160ab12cd 100644 --- a/server/src/dtos/system-config.dto.ts +++ b/server/src/dtos/system-config.dto.ts @@ -181,7 +181,12 @@ const SystemConfigOAuthSchema = z timeout: z.int().min(1).describe('Timeout'), defaultStorageQuota: z.number().min(0).nullable().describe('Default storage quota'), enabled: configBool.describe('Enabled'), - issuerUrl: z.string().describe('Issuer URL'), + issuerUrl: z + .string() + .refine((url) => url.length === 0 || z.url().safeParse(url).success, { + error: 'Issuer URL must be an empty string or a valid URL', + }) + .describe('Issuer URL'), scope: z.string().describe('Scope'), signingAlgorithm: z.string().describe('Signing algorithm'), profileSigningAlgorithm: z.string().describe('Profile signing algorithm'), diff --git a/server/src/services/system-config.service.spec.ts b/server/src/services/system-config.service.spec.ts index bb68f70d13..a9d2e35507 100644 --- a/server/src/services/system-config.service.spec.ts +++ b/server/src/services/system-config.service.spec.ts @@ -307,6 +307,15 @@ describe(SystemConfigService.name, () => { }); }); + it('should reject an invalid issuer URL', async () => { + mocks.config.getEnv.mockReturnValue(mockEnvData({ configFile: 'immich-config.json' })); + mocks.systemMetadata.readFile.mockResolvedValue(JSON.stringify({ oauth: { issuerUrl: 'accounts.google.com' } })); + + await expect(sut.getSystemConfig()).rejects.toThrow( + '[oauth.issuerUrl] Issuer URL must be an empty string or a valid URL', + ); + }); + it('should reject invalid cron expressions', async () => { mocks.config.getEnv.mockReturnValue(mockEnvData({ configFile: 'immich-config.json' })); mocks.systemMetadata.readFile.mockResolvedValue(JSON.stringify({ library: { scan: { cronExpression: 'foo' } } }));