Skip to content

Commit

Permalink
fix: image optimization content-type (#46219)
Browse files Browse the repository at this point in the history
Upstream images can have any arbitrary `content-type` header so this PR
normalizes the value before checking it.
  • Loading branch information
styfle authored Feb 22, 2023
1 parent b8837ad commit 0b563e8
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 11 deletions.
26 changes: 15 additions & 11 deletions packages/next/src/server/image-optimizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -573,25 +573,29 @@ export async function imageOptimizer(
}
}

if (upstreamType === SVG && !nextConfig.images.dangerouslyAllowSVG) {
console.error(
`The requested resource "${href}" has type "${upstreamType}" but dangerouslyAllowSVG is disabled`
)
throw new ImageError(
400,
'"url" parameter is valid but image type is not allowed'
)
}

if (upstreamType) {
upstreamType = upstreamType.toLowerCase().trim()

if (
upstreamType.startsWith('image/svg') &&
!nextConfig.images.dangerouslyAllowSVG
) {
console.error(
`The requested resource "${href}" has type "${upstreamType}" but dangerouslyAllowSVG is disabled`
)
throw new ImageError(
400,
'"url" parameter is valid but image type is not allowed'
)
}
const vector = VECTOR_TYPES.includes(upstreamType)
const animate =
ANIMATABLE_TYPES.includes(upstreamType) && isAnimated(upstreamBuffer)

if (vector || animate) {
return { buffer: upstreamBuffer, contentType: upstreamType, maxAge }
}
if (!upstreamType.startsWith('image/')) {
if (!upstreamType.startsWith('image/') || upstreamType.includes(',')) {
console.error(
"The requested resource isn't a valid image for",
href,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default function handler(_req, res) {
res.setHeader('Content-Type', 'application/svg+xml')
res.end(
`<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="60" height="60"><text x="20" y="30">hi</text></svg>`
)
}
6 changes: 6 additions & 0 deletions test/integration/image-optimizer/app/pages/api/comma.svg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default function handler(_req, res) {
res.setHeader('Content-Type', 'image/foo, text/html')
res.end(
`<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="60" height="60"><text x="20" y="30">hi</text></svg>`
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default function handler(_req, res) {
res.setHeader('Content-Type', 'image/SVG+XML')
res.end(
`<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="60" height="60"><text x="20" y="30">hi</text></svg>`
)
}
30 changes: 30 additions & 0 deletions test/integration/image-optimizer/test/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,36 @@ export function runTests(ctx) {
expect(res.status).toBe(400)
expect(await res.text()).toContain('valid but image type is not allowed')
})

it('should not allow svg with application header', async () => {
const query = { w: ctx.w, q: 45, url: '/api/application.svg' }
const opts = { headers: { accept: 'image/webp' } }
const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, opts)
expect(res.status).toBe(400)
expect(await res.text()).toContain(
"The requested resource isn't a valid image"
)
})

it('should not allow svg with comma header', async () => {
const query = { w: ctx.w, q: 55, url: '/api/comma.svg' }
const opts = { headers: { accept: 'image/webp' } }
const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, opts)
expect(res.status).toBe(400)
expect(await res.text()).toContain(
"The requested resource isn't a valid image"
)
})

it('should not allow svg with uppercase header', async () => {
const query = { w: ctx.w, q: 65, url: '/api/uppercase.svg' }
const opts = { headers: { accept: 'image/webp' } }
const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, opts)
expect(res.status).toBe(400)
expect(await res.text()).toContain(
'"url" parameter is valid but image type is not allowed'
)
})
}

it('should maintain ico format', async () => {
Expand Down

0 comments on commit 0b563e8

Please sign in to comment.