Skip to content

Commit c7860ab

Browse files
authored
Merge pull request #330 from netlify/mk/webp-doc
fix: use allowlist for remote images
2 parents 1ff8d34 + 20b1288 commit c7860ab

File tree

3 files changed

+35
-4
lines changed

3 files changed

+35
-4
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,14 @@ Similarly, you can customize your publish directory in your `netlify.toml` file:
126126

127127
Read more about [Netlify's build settings](https://docs.netlify.com/configure-builds/get-started/#basic-build-settings) in our docs.
128128

129+
## Image handling
130+
131+
The plugin includes a function to generate images for `next/image`. The images are resized on the fly, so the first request will have a short delay. However because the function uses [On-Demand Builders](https://docs.netlify.com/configure-builds/on-demand-builders/), any subsequent requests for that image are served from the edge cache and are super-fast.
132+
133+
By default, images are returned in the same format as the source image if they are in JPEG, PNG, WebP or AVIF format. If you are only targeting modern browsers and want to live life on the edge, you can [set the environment variable](https://docs.netlify.com/configure-builds/environment-variables/) `FORCE_WEBP_OUTPUT` to `"true"`, and it will return all images in WebP format. This will often lead to significant improvements in file size. However you should not use this if you need to support older browsers, as `next/image` does not support picture tag source fallback and images will appear broken. Check [browser support](https://caniuse.com/webp) to see if you are happy to do this.
134+
135+
If you want to use remote images in `next/image`, you will need to add the image domains to an allow list. Setting them in `images.domains` in `next.config.js` is not supported: instead you should set the environment variable `NEXT_IMAGE_ALLOWED_DOMAINS` to a comma-separated list of domains, e.g. `NEXT_IMAGE_ALLOWED_DOMAINS="placekitten.com,unsplash.com"`.
136+
129137
## Custom Netlify Redirects
130138

131139
You can define custom redirects in a `_redirects` file.

index.js

+8
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ module.exports = {
4646

4747
// Because we memoize nextConfig, we need to do this after the write file
4848
const nextConfig = await getNextConfig(utils.failBuild)
49+
50+
if (nextConfig.images.domains.length !== 0 && !process.env.NEXT_IMAGE_ALLOWED_DOMAINS) {
51+
console.log(
52+
`Image domains set in next.config.js are ignored.\nPlease set the env variable NEXT_IMAGE_ALLOWED_DOMAINS to "${nextConfig.images.domains.join(
53+
',',
54+
)}" instead`,
55+
)
56+
}
4957
await restoreCache({ cache: utils.cache, distDir: nextConfig.distDir })
5058
},
5159
async onBuild({

src/lib/templates/imageFunction.js

+19-4
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,24 @@ const handler = async (event) => {
3434

3535
const quality = parseInt(q) || 60
3636

37-
const imageUrl = parsedUrl.startsWith('/')
38-
? `${process.env.DEPLOY_URL || `http://${event.headers.host}`}${parsedUrl}`
39-
: parsedUrl
37+
let imageUrl
38+
// Relative image
39+
if (parsedUrl.startsWith('/')) {
40+
imageUrl = `${process.env.DEPLOY_URL || `http://${event.headers.host}`}${parsedUrl}`
41+
} else {
42+
// Remote images need to be in the allowlist
43+
const allowedDomains = process.env.NEXT_IMAGE_ALLOWED_DOMAINS
44+
? process.env.NEXT_IMAGE_ALLOWED_DOMAINS.split(',').map((domain) => domain.trim())
45+
: []
46+
47+
if (!allowedDomains.includes(new URL(parsedUrl).hostname)) {
48+
return {
49+
statusCode: 403,
50+
body: 'Image is not from a permitted domain',
51+
}
52+
}
53+
imageUrl = parsedUrl
54+
}
4055

4156
const imageData = await fetch(imageUrl)
4257

@@ -68,7 +83,7 @@ const handler = async (event) => {
6883
}
6984
}
7085

71-
if (process.env.FORCE_WEBP_OUTPUT) {
86+
if (process.env.FORCE_WEBP_OUTPUT === 'true' || process.env.FORCE_WEBP_OUTPUT === '1') {
7287
ext = 'webp'
7388
}
7489

0 commit comments

Comments
 (0)