From 8fab98f3f1f767d05825d24cbf155d56375fdb3e Mon Sep 17 00:00:00 2001 From: Tomi Turtiainen <10324676+tomi@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:52:17 +0200 Subject: [PATCH] fix(core): Use timing safe function to compare runner auth tokens (#12485) --- .../auth/__tests__/task-runner-auth.service.test.ts | 4 ++-- .../src/task-runners/auth/task-runner-auth.service.ts | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/task-runners/auth/__tests__/task-runner-auth.service.test.ts b/packages/cli/src/task-runners/auth/__tests__/task-runner-auth.service.test.ts index a1321945e3..66581ffce0 100644 --- a/packages/cli/src/task-runners/auth/__tests__/task-runner-auth.service.test.ts +++ b/packages/cli/src/task-runners/auth/__tests__/task-runner-auth.service.test.ts @@ -33,11 +33,11 @@ describe('TaskRunnerAuthService', () => { describe('isValidAuthToken', () => { it('should be valid for the configured token', () => { - expect(authService.isValidAuthToken('random-secret')); + expect(authService.isValidAuthToken('random-secret')).toBe(true); }); it('should be invalid for anything else', () => { - expect(authService.isValidAuthToken('!random-secret')); + expect(authService.isValidAuthToken('!random-secret')).toBe(false); }); }); diff --git a/packages/cli/src/task-runners/auth/task-runner-auth.service.ts b/packages/cli/src/task-runners/auth/task-runner-auth.service.ts index c16afc5c63..770a5ae1fa 100644 --- a/packages/cli/src/task-runners/auth/task-runner-auth.service.ts +++ b/packages/cli/src/task-runners/auth/task-runner-auth.service.ts @@ -1,6 +1,6 @@ import { GlobalConfig } from '@n8n/config'; import { Service } from '@n8n/di'; -import { randomBytes } from 'crypto'; +import { randomBytes, timingSafeEqual } from 'crypto'; import { Time } from '@/constants'; import { CacheService } from '@/services/cache/cache.service'; @@ -9,6 +9,8 @@ const GRANT_TOKEN_TTL = 15 * Time.seconds.toMilliseconds; @Service() export class TaskRunnerAuthService { + private readonly authToken = Buffer.from(this.globalConfig.taskRunners.authToken); + constructor( private readonly globalConfig: GlobalConfig, private readonly cacheService: CacheService, @@ -17,7 +19,10 @@ export class TaskRunnerAuthService { ) {} isValidAuthToken(token: string) { - return token === this.globalConfig.taskRunners.authToken; + const tokenBuffer = Buffer.from(token); + if (tokenBuffer.length !== this.authToken.length) return false; + + return timingSafeEqual(tokenBuffer, this.authToken); } /**