From da7fb13d83615465c77609ef6159d545a1b415cf Mon Sep 17 00:00:00 2001 From: Peter White <1788320+peterwhite@users.noreply.github.com> Date: Mon, 24 Aug 2026 12:11:40 +0200 Subject: [PATCH] Fail closed in /~gitbook/revalidate when GITBOOK_SECRET is unset (#4535) --- .changeset/revalidate-fail-closed.md | 5 +++++ packages/gitbook/src/lib/routes.ts | 31 +++++++++++++++------------- 2 files changed, 22 insertions(+), 14 deletions(-) create mode 100644 .changeset/revalidate-fail-closed.md diff --git a/.changeset/revalidate-fail-closed.md b/.changeset/revalidate-fail-closed.md new file mode 100644 index 000000000..568e5e353 --- /dev/null +++ b/.changeset/revalidate-fail-closed.md @@ -0,0 +1,5 @@ +--- +"gitbook": patch +--- + +Fail closed in `/~gitbook/revalidate` when `GITBOOK_SECRET` is not configured, returning `403 Revalidation is disabled` instead of skipping the signature check, consistent with `force-revalidate`. diff --git a/packages/gitbook/src/lib/routes.ts b/packages/gitbook/src/lib/routes.ts index 24f114114..4b4e56b9b 100644 --- a/packages/gitbook/src/lib/routes.ts +++ b/packages/gitbook/src/lib/routes.ts @@ -10,26 +10,29 @@ export async function withVerifySignature( request: Request, fn: (body: T) => Promise ) { + // Fail closed when no secret is configured, consistent with force-revalidate. + if (!GITBOOK_SECRET) { + return NextResponse.json({ error: 'Revalidation is disabled' }, { status: 403 }); + } + try { const rawBody = await request.text(); const body = JSON.parse(rawBody) as T; - if (GITBOOK_SECRET) { - // Retrieve the signature header from the request - const incomingSignature = request.headers.get('x-gitbook-signature'); - if (!incomingSignature) { - return NextResponse.json({ error: 'Missing signature header' }, { status: 400 }); - } + // Retrieve the signature header from the request + const incomingSignature = request.headers.get('x-gitbook-signature'); + if (!incomingSignature) { + return NextResponse.json({ error: 'Missing signature header' }, { status: 400 }); + } - const computedSignature = crypto - .createHmac('sha256', GITBOOK_SECRET) - .update(rawBody) - .digest('hex'); + const computedSignature = crypto + .createHmac('sha256', GITBOOK_SECRET) + .update(rawBody) + .digest('hex'); - // Compare incoming signature to computed signature - if (incomingSignature !== computedSignature) { - return NextResponse.json({ error: 'Invalid signature' }, { status: 401 }); - } + // Compare incoming signature to computed signature + if (incomingSignature !== computedSignature) { + return NextResponse.json({ error: 'Invalid signature' }, { status: 401 }); } return await fn(body);