feat(next/image)!: deprecate and warn on images.domains config (#84625)

This was docs deprecated in Next.js 14 so we should begin warning in
Next.js 16 when `images.domains` config is used.

This will guide users to providing a strict `images.remotePatterns`
config ensuring only expected images can be optimized.
This commit is contained in:
Steven
2025-10-07 23:21:36 -04:00
committed by GitHub
parent 8c52bd604e
commit 364db96f05
4 changed files with 35 additions and 6 deletions
@@ -871,10 +871,12 @@ You can optionally configure `inline` to allow the browser to render the image w
#### `domains`
> **Warning**: Deprecated since Next.js 14 in favor of strict [`remotePatterns`](#remotepatterns) in order to protect your application from malicious users. Only use `domains` if you own all the content served from the domain.
> **Warning**: Deprecated since Next.js 14 in favor of strict [`remotePatterns`](#remotepatterns) in order to protect your application from malicious users.
Similar to [`remotePatterns`](#remotepatterns), the `domains` configuration can be used to provide a list of allowed hostnames for external images. However, the `domains` configuration does not support wildcard pattern matching and it cannot restrict protocol, port, or pathname.
Since most remote image servers are shared between multiple tenants, it's safer to use `remotePatterns` to ensure only the intended images are optimized.
Below is an example of the `domains` property in the `next.config.js` file:
```js filename="next.config.js"
+9
View File
@@ -120,6 +120,15 @@ function checkDeprecations(
silent
)
if (userConfig.images?.domains?.length) {
warnOptionHasBeenDeprecated(
userConfig,
'images.domains',
`\`images.domains\` is deprecated in favor of \`images.remotePatterns\`. Please update ${configFileName} to protect your application from malicious users.`,
silent
)
}
// i18n deprecation for App Router
if (userConfig.i18n) {
const hasAppDir = Boolean(findDir(dir, 'app'))
@@ -133,6 +133,9 @@ export const imageConfigDefault: ImageConfigComplete = {
path: '/_next/image',
loader: 'default',
loaderFile: '',
/**
* @deprecated Use `remotePatterns` instead to protect your application from malicious users.
*/
domains: [],
disableStaticImages: false,
minimumCacheTTL: 14400, // 4 hours
@@ -13,7 +13,7 @@ const appDir = join(__dirname, '../')
let appPort
let app
function runTests() {
function runTests(getOutput: () => string) {
it('should apply image config for node_modules', async () => {
const browser = await webdriver(appPort, '/')
const src = await browser
@@ -26,14 +26,25 @@ function runTests() {
.getAttribute('srcset')
expect(srcset).toMatch('1234')
})
it('should warn when using images.domains config', async () => {
expect(getOutput()).toContain(
'`images.domains` is deprecated in favor of `images.remotePatterns`. Please update next.config.js to protect your application from malicious users.'
)
})
}
describe('Image Component from node_modules prod mode', () => {
;(process.env.TURBOPACK_DEV ? describe.skip : describe)(
'production mode',
() => {
let output = ''
beforeAll(async () => {
await nextBuild(appDir)
const result = await nextBuild(appDir, [], {
stderr: true,
stdout: true,
})
output = (result.stderr ?? '') + (result.stdout ?? '')
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
@@ -41,19 +52,23 @@ describe('Image Component from node_modules prod mode', () => {
await killApp(app)
})
runTests()
runTests(() => output)
}
)
})
describe('Image Component from node_modules development mode', () => {
let output = ''
beforeAll(async () => {
appPort = await findPort()
app = await launchApp(appDir, appPort)
app = await launchApp(appDir, appPort, {
onStderr: (msg) => (output += msg),
onStdout: (msg) => (output += msg),
})
})
afterAll(async () => {
await killApp(app)
})
runTests()
runTests(() => output)
})