Prevent SVG images to be resized and rendered on the /~gitbook/image endpoint (#2362)

This commit is contained in:
Johan Preynat
2024-06-27 12:24:46 +02:00
committed by GitHub
parent 7c26d491b1
commit 6929b0b98b
2 changed files with 16 additions and 5 deletions
+7 -1
View File
@@ -1,6 +1,6 @@
import { NextRequest } from 'next/server';
import { verifyImageSignature, resizeImage, CloudflareImageOptions } from '@/lib/images';
import { verifyImageSignature, resizeImage, CloudflareImageOptions, checkIsSizableImageURL } from '@/lib/images';
import { parseImageAPIURL } from '@/lib/urls';
export const runtime = 'edge';
@@ -27,6 +27,12 @@ export async function GET(request: NextRequest) {
return new Response('Invalid url parameter', { status: 400 });
}
// Check again if the image can be sized, even though we checked when rendering the Image component
// Otherwise, it's possible to pass just any link to this endpoint and trigger HTML injection on the domain
if (!checkIsSizableImageURL(url)) {
return new Response('Invalid url parameter', { status: 400 });
}
// Verify the signature
const verified = await verifyImageSignature(url, { signature, version: signatureVersion });
if (!verified) {
+9 -4
View File
@@ -41,7 +41,7 @@ export function isImageResizingEnabled(): boolean {
/**
* Check if a URL is an HTTP URL.
*/
export function checkIsHttpURL(input: string): boolean {
export function checkIsHttpURL(input: string | URL): boolean {
if (!URL.canParse(input)) {
return false;
}
@@ -54,11 +54,16 @@ export function checkIsHttpURL(input: string): boolean {
* Skip it for non-http(s) URLs (data, etc).
* Skip it for SVGs.
*/
function checkIsSizableImageURL(input: string): boolean {
if (input.endsWith('.svg')) {
export function checkIsSizableImageURL(input: string): boolean {
if (!URL.canParse(input)) {
return false;
}
return checkIsHttpURL(input);
const parsed = new URL(input);
if (parsed.pathname.endsWith('.svg')) {
return false;
}
return checkIsHttpURL(parsed);
}
/**