fix(core): Use timing safe function to compare runner auth tokens (#12485)

This commit is contained in:
Tomi Turtiainen 2025-01-09 12:52:17 +02:00 committed by GitHub
parent 7583e2ad94
commit 8fab98f3f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 9 additions and 4 deletions

View file

@ -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);
});
});

View file

@ -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);
}
/**