From e929e184b780d825b74a0f14b214bfff2f1e2b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Berg=C3=A9?= Date: Tue, 14 Jan 2025 12:09:07 +0100 Subject: [PATCH 1/3] Allow only valid values for theme query string Fix GITBOOK-OPEN-1X8D --- .changeset/loud-files-tap.md | 5 +++++ packages/gitbook/src/middleware.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/loud-files-tap.md diff --git a/.changeset/loud-files-tap.md b/.changeset/loud-files-tap.md new file mode 100644 index 000000000..fbc677952 --- /dev/null +++ b/.changeset/loud-files-tap.md @@ -0,0 +1,5 @@ +--- +'gitbook': patch +--- + +Allow only good values for theme query parameter. Avoid having a 500 error when we pass an invalid value. diff --git a/packages/gitbook/src/middleware.ts b/packages/gitbook/src/middleware.ts index e435ca3d7..052d5eee7 100644 --- a/packages/gitbook/src/middleware.ts +++ b/packages/gitbook/src/middleware.ts @@ -264,7 +264,7 @@ export async function middleware(request: NextRequest) { } const theme = url.searchParams.get('theme'); - if (theme) { + if (theme === 'dark' || theme === 'light') { headers.set('x-gitbook-theme', theme); } From 370d6a7fc13cbf58ee8d841357007d71ddabdfe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Berg=C3=A9?= Date: Tue, 14 Jan 2025 12:12:34 +0100 Subject: [PATCH 2/3] Allow only valid values for x-gitbook-customization header --- packages/gitbook/src/middleware.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/gitbook/src/middleware.ts b/packages/gitbook/src/middleware.ts index 052d5eee7..8e2112c31 100644 --- a/packages/gitbook/src/middleware.ts +++ b/packages/gitbook/src/middleware.ts @@ -5,6 +5,7 @@ import jwt from 'jsonwebtoken'; import type { ResponseCookie } from 'next/dist/compiled/@edge-runtime/cookies'; import { NextResponse, NextRequest } from 'next/server'; import hash from 'object-hash'; +import rison from 'rison'; import { PublishedContentWithCache, @@ -260,7 +261,10 @@ export async function middleware(request: NextRequest) { const customization = url.searchParams.get('customization'); if (customization) { - headers.set('x-gitbook-customization', customization); + try { + rison.decode_object(customization); + headers.set('x-gitbook-customization', customization); + } catch {} } const theme = url.searchParams.get('theme'); From a32b9b2c7dc89f72aef9f17e0e754158d29c46ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Berg=C3=A9?= Date: Tue, 14 Jan 2025 12:16:27 +0100 Subject: [PATCH 3/3] Refactor code --- packages/gitbook/src/lib/api.ts | 12 ++++++++++++ packages/gitbook/src/middleware.ts | 12 +++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/gitbook/src/lib/api.ts b/packages/gitbook/src/lib/api.ts index 94b819b18..52ffefd39 100644 --- a/packages/gitbook/src/lib/api.ts +++ b/packages/gitbook/src/lib/api.ts @@ -876,6 +876,18 @@ export async function getSiteData( }; } +/** + * Validate that the customization settings passed are valid. + */ +export function validateSerializedCustomization(raw: string): boolean { + try { + rison.decode_object(raw); + return true; + } catch { + return false; + } +} + /** * Get the customization settings for a space from the API. */ diff --git a/packages/gitbook/src/middleware.ts b/packages/gitbook/src/middleware.ts index 8e2112c31..7378145fc 100644 --- a/packages/gitbook/src/middleware.ts +++ b/packages/gitbook/src/middleware.ts @@ -1,4 +1,4 @@ -import { ContentAPITokenPayload, GitBookAPI } from '@gitbook/api'; +import { ContentAPITokenPayload, CustomizationThemeMode, GitBookAPI } from '@gitbook/api'; import { setTag, setContext } from '@sentry/nextjs'; import assertNever from 'assert-never'; import jwt from 'jsonwebtoken'; @@ -18,6 +18,7 @@ import { DEFAULT_API_ENDPOINT, getPublishedContentSite, getSiteData, + validateSerializedCustomization, } from '@/lib/api'; import { race } from '@/lib/async'; import { buildVersion } from '@/lib/build'; @@ -260,15 +261,12 @@ export async function middleware(request: NextRequest) { } const customization = url.searchParams.get('customization'); - if (customization) { - try { - rison.decode_object(customization); - headers.set('x-gitbook-customization', customization); - } catch {} + if (customization && validateSerializedCustomization(customization)) { + headers.set('x-gitbook-customization', customization); } const theme = url.searchParams.get('theme'); - if (theme === 'dark' || theme === 'light') { + if (theme === CustomizationThemeMode.Dark || theme === CustomizationThemeMode.Light) { headers.set('x-gitbook-theme', theme); }