Skip to content

Commit 7afc97c

Browse files
authored
Add CSP to Image Optimization API (#28620)
Add CSP header to Image Optimization API
1 parent 8711c5c commit 7afc97c

File tree

5 files changed

+45
-1
lines changed

5 files changed

+45
-1
lines changed

packages/next/server/image-optimizer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,8 @@ function setResponseHeaders(
525525
res.setHeader('Content-Disposition', `inline; filename="${fileName}"`)
526526
}
527527

528+
res.setHeader('Content-Security-Policy', `script-src 'none'; sandbox;`)
529+
528530
return { finished: false }
529531
}
530532

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from 'react'
2+
import Image from 'next/image'
3+
4+
const Page = () => {
5+
return (
6+
<div>
7+
<h1>SVG with a script tag attempting XSS</h1>
8+
<Image id="img" src="/xss.svg" width="100" height="100" />
9+
<p id="msg">safe</p>
10+
</div>
11+
)
12+
}
13+
14+
export default Page
Lines changed: 9 additions & 0 deletions
Loading

test/integration/production/test/index.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ describe('Production Usage', () => {
7878
})
7979

8080
it('should contain generated page count in output', async () => {
81-
const pageCount = process.env.NEXT_PRIVATE_TEST_WEBPACK4_MODE ? 37 : 38
81+
const pageCount = process.env.NEXT_PRIVATE_TEST_WEBPACK4_MODE ? 38 : 39
8282
expect(output).toContain(`Generating static pages (0/${pageCount})`)
8383
expect(output).toContain(
8484
`Generating static pages (${pageCount}/${pageCount})`

test/integration/production/test/security.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,5 +342,24 @@ module.exports = (context) => {
342342
expect(pathname).toBe('/%2fexample.com')
343343
expect(hostname).not.toBe('example.com')
344344
})
345+
346+
it('should not execute script embedded inside svg image', async () => {
347+
let browser
348+
try {
349+
browser = await webdriver(context.appPort, '/svg-image')
350+
await browser.eval(`document.getElementById("img").scrollIntoView()`)
351+
expect(await browser.elementById('img').getAttribute('src')).toContain(
352+
'xss.svg'
353+
)
354+
expect(await browser.elementById('msg').text()).toBe('safe')
355+
browser = await webdriver(
356+
context.appPort,
357+
'/_next/image?url=%2Fxss.svg&w=256&q=75'
358+
)
359+
expect(await browser.elementById('msg').text()).toBe('safe')
360+
} finally {
361+
if (browser) await browser.close()
362+
}
363+
})
345364
})
346365
}

0 commit comments

Comments
 (0)