Skip to content

Commit b82f857

Browse files
committed
Use constant-time compare for admin auth
1 parent 7398965 commit b82f857

2 files changed

Lines changed: 3 additions & 3 deletions

File tree

apps/license-server/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Hono } from 'hono'
22
import { generateLicenseKey, generateShortCode, isValidShortCode, type LicenseType } from './license'
33
import { sendLicenseEmail } from './email'
4-
import { verifyPaddleWebhookMulti } from './paddle'
4+
import { constantTimeEqual, verifyPaddleWebhookMulti } from './paddle'
55
import {
66
getSubscriptionStatus,
77
getLicenseTypeFromPriceId,
@@ -349,7 +349,7 @@ app.post('/admin/generate', async (c) => {
349349
const validSecrets = [c.env.PADDLE_WEBHOOK_SECRET_LIVE, c.env.PADDLE_WEBHOOK_SECRET_SANDBOX].filter(
350350
(s): s is string => !!s,
351351
)
352-
const isAuthorized = validSecrets.some((secret) => authHeader === `Bearer ${secret}`)
352+
const isAuthorized = validSecrets.some((secret) => constantTimeEqual(authHeader ?? '', `Bearer ${secret}`))
353353
if (!isAuthorized) {
354354
return c.json({ error: 'Unauthorized' }, 401)
355355
}

apps/license-server/src/paddle.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/** XOR-accumulate comparison that always inspects every byte, preventing timing attacks. */
2-
function constantTimeEqual(a: string, b: string): boolean {
2+
export function constantTimeEqual(a: string, b: string): boolean {
33
if (a.length !== b.length) return false
44
let mismatch = 0
55
for (let i = 0; i < a.length; i++) {

0 commit comments

Comments
 (0)