@@ -93,12 +93,16 @@ export async function fetchImage(fetcher: Fetcher | undefined, imageUrl: string,
93
93
}
94
94
95
95
if ( ! contentType ) {
96
- // Fallback to the sanitized upstream header when the type can not be detected
96
+ // Fallback to upstream header when the type can not be detected
97
97
// https://github.com/vercel/next.js/blob/d76f0b1/packages/next/src/server/image-optimizer.ts#L748
98
- const header = imgResponse . headers . get ( "content-type" ) ?? "" ;
99
- if ( header . startsWith ( "image/" ) && ! header . includes ( "," ) ) {
100
- contentType = header ;
101
- }
98
+ contentType = imgResponse . headers . get ( "content-type" ) ?? "" ;
99
+ }
100
+
101
+ // Sanitize the content type:
102
+ // - Accept images only
103
+ // - Reject multiple content types
104
+ if ( ! contentType . startsWith ( "image/" ) || contentType . includes ( "," ) ) {
105
+ contentType = undefined ;
102
106
}
103
107
104
108
if ( contentType && ! ( contentType === SVG && ! __IMAGES_ALLOW_SVG__ ) ) {
@@ -167,12 +171,17 @@ const AVIF = "image/avif";
167
171
const WEBP = "image/webp" ;
168
172
const PNG = "image/png" ;
169
173
const JPEG = "image/jpeg" ;
174
+ const JXL = "image/jxl" ;
175
+ const JP2 = "image/jp2" ;
176
+ const HEIC = "image/heic" ;
170
177
const GIF = "image/gif" ;
171
178
const SVG = "image/svg+xml" ;
172
179
const ICO = "image/x-icon" ;
173
180
const ICNS = "image/x-icns" ;
174
181
const TIFF = "image/tiff" ;
175
182
const BMP = "image/bmp" ;
183
+ // pdf will be rejected (not an `image/...` type)
184
+ const PDF = "application/pdf" ;
176
185
177
186
/**
178
187
* Detects the content type by looking at the first few bytes of a file
@@ -216,6 +225,25 @@ export function detectContentType(buffer: Uint8Array) {
216
225
if ( [ 0x42 , 0x4d ] . every ( ( b , i ) => buffer [ i ] === b ) ) {
217
226
return BMP ;
218
227
}
228
+ if ( [ 0xff , 0x0a ] . every ( ( b , i ) => buffer [ i ] === b ) ) {
229
+ return JXL ;
230
+ }
231
+ if (
232
+ [ 0x00 , 0x00 , 0x00 , 0x0c , 0x4a , 0x58 , 0x4c , 0x20 , 0x0d , 0x0a , 0x87 , 0x0a ] . every ( ( b , i ) => buffer [ i ] === b )
233
+ ) {
234
+ return JXL ;
235
+ }
236
+ if ( [ 0 , 0 , 0 , 0 , 0x66 , 0x74 , 0x79 , 0x70 , 0x68 , 0x65 , 0x69 , 0x63 ] . every ( ( b , i ) => ! b || buffer [ i ] === b ) ) {
237
+ return HEIC ;
238
+ }
239
+ if ( [ 0x25 , 0x50 , 0x44 , 0x46 , 0x2d ] . every ( ( b , i ) => buffer [ i ] === b ) ) {
240
+ return PDF ;
241
+ }
242
+ if (
243
+ [ 0x00 , 0x00 , 0x00 , 0x0c , 0x6a , 0x50 , 0x20 , 0x20 , 0x0d , 0x0a , 0x87 , 0x0a ] . every ( ( b , i ) => buffer [ i ] === b )
244
+ ) {
245
+ return JP2 ;
246
+ }
219
247
}
220
248
221
249
declare global {
0 commit comments