From c04c257712864668a531883ee42fb2ba2688cd39 Mon Sep 17 00:00:00 2001 From: Kendell Joseph <1900724+kendelljoseph@users.noreply.github.com> Date: Thu, 12 Jun 2025 09:46:49 -0400 Subject: [PATCH] chore: adds filters (#12622) Filters URLs to avoid issues with SSRF Had to use `undici` instead of native `fetch` because it was the only viable alternative that supported both overriding agent/dispatch and also implemented `credentials: include`. [More info here.](https://blog.doyensec.com/2023/03/16/ssrf-remediation-bypass.html) --------- Co-authored-by: Elliot DeNolf --- packages/payload/package.json | 2 + .../payload/src/uploads/getExternalFile.ts | 3 +- packages/payload/src/uploads/safeFetch.ts | 71 +++ pnpm-lock.yaml | 517 ++++++++++++------ test/uploads/config.ts | 22 + test/uploads/int.spec.ts | 43 ++ test/uploads/payload-types.ts | 41 ++ test/uploads/shared.ts | 1 + 8 files changed, 519 insertions(+), 181 deletions(-) create mode 100644 packages/payload/src/uploads/safeFetch.ts diff --git a/packages/payload/package.json b/packages/payload/package.json index 7f8d87fbb..db25a4974 100644 --- a/packages/payload/package.json +++ b/packages/payload/package.json @@ -99,6 +99,7 @@ "get-tsconfig": "4.8.1", "http-status": "2.1.0", "image-size": "2.0.2", + "ipaddr.js": "2.2.0", "jose": "5.9.6", "json-schema-to-typescript": "15.0.3", "minimist": "1.2.8", @@ -111,6 +112,7 @@ "scmp": "2.1.0", "ts-essentials": "10.0.3", "tsx": "4.19.2", + "undici": "7.10.0", "uuid": "10.0.0", "ws": "^8.16.0" }, diff --git a/packages/payload/src/uploads/getExternalFile.ts b/packages/payload/src/uploads/getExternalFile.ts index b24b14f1d..d932f45b5 100644 --- a/packages/payload/src/uploads/getExternalFile.ts +++ b/packages/payload/src/uploads/getExternalFile.ts @@ -2,6 +2,7 @@ import type { PayloadRequest } from '../types/index.js' import type { File, FileData, UploadConfig } from './types.js' import { APIError } from '../errors/index.js' +import { safeFetch } from './safeFetch.js' type Args = { data: FileData @@ -22,7 +23,7 @@ export const getExternalFile = async ({ data, req, uploadConfig }: Args): Promis ? uploadConfig.externalFileHeaderFilter(Object.fromEntries(new Headers(req.headers))) : { cookie: req.headers.get('cookie')! } - const res = await fetch(fileURL, { + const res = await safeFetch(fileURL, { credentials: 'include', headers, method: 'GET', diff --git a/packages/payload/src/uploads/safeFetch.ts b/packages/payload/src/uploads/safeFetch.ts new file mode 100644 index 000000000..44806e5c2 --- /dev/null +++ b/packages/payload/src/uploads/safeFetch.ts @@ -0,0 +1,71 @@ +import type { Dispatcher } from 'undici' + +import ipaddr from 'ipaddr.js' +import { Agent, fetch as undiciFetch } from 'undici' + +const isSafeIp = (ip: string) => { + try { + if (!ip) { + return false + } + + if (!ipaddr.isValid(ip)) { + return false + } + + const parsedIpAddress = ipaddr.parse(ip) + const range = parsedIpAddress.range() + if (range !== 'unicast') { + return false // Private IP Range + } + } catch (ignore) { + return false + } + return true +} + +const ssrfFilterInterceptor: Dispatcher.DispatcherComposeInterceptor = (dispatch) => { + return (opts, handler) => { + const url = new URL(opts.origin?.toString() + opts.path) + if (!isSafeIp(url.hostname)) { + throw new Error(`Blocked unsafe attempt to ${url}`) + } + return dispatch(opts, handler) + } +} + +const safeDispatcher = new Agent().compose(ssrfFilterInterceptor) + +/** + * A "safe" version of undici's fetch that prevents SSRF attacks. + * + * - Utilizes a custom dispatcher that filters out requests to unsafe IP addresses. + * - Undici was used because it supported interceptors as well as "credentials: include". Native fetch + */ +export const safeFetch = async (...args: Parameters) => { + const [url, options] = args + try { + return await undiciFetch(url, { + ...options, + dispatcher: safeDispatcher, + }) + } catch (error) { + if (error instanceof Error) { + if (error.cause instanceof Error && error.cause.message.includes('unsafe')) { + // Errors thrown from within interceptors always have 'fetch error' as the message + // The desired message we want to bubble up is in the cause + throw new Error(error.cause.message) + } else { + let stringifiedUrl: string | undefined | URL = undefined + if (typeof url === 'string' || url instanceof URL) { + stringifiedUrl = url + } else if (url instanceof Request) { + stringifiedUrl = url.url + } + + throw new Error(`Failed to fetch from ${stringifiedUrl}, ${error.message}`) + } + } + throw error + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 29325a4de..7e0236348 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -727,7 +727,7 @@ importers: version: 2.1.0 next: specifier: ^15.2.3 - version: 15.3.0(@babel/core@7.27.3)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.77.4) + version: 15.2.3(@babel/core@7.27.3)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.77.4) path-to-regexp: specifier: 6.3.0 version: 6.3.0 @@ -843,6 +843,9 @@ importers: image-size: specifier: 2.0.2 version: 2.0.2 + ipaddr.js: + specifier: 2.2.0 + version: 2.2.0 jose: specifier: 5.9.6 version: 5.9.6 @@ -879,6 +882,9 @@ importers: tsx: specifier: 4.19.2 version: 4.19.2 + undici: + specifier: 7.10.0 + version: 7.10.0 uuid: specifier: 10.0.0 version: 10.0.0 @@ -1069,7 +1075,7 @@ importers: dependencies: next: specifier: ^15.2.3 - version: 15.3.0(@babel/core@7.27.3)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.77.4) + version: 15.2.3(@babel/core@7.27.3)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.77.4) devDependencies: '@payloadcms/eslint-config': specifier: workspace:* @@ -1583,7 +1589,7 @@ importers: version: 2.3.0 next: specifier: ^15.2.3 - version: 15.3.0(@babel/core@7.27.3)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.77.4) + version: 15.2.3(@babel/core@7.27.3)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.77.4) object-to-formdata: specifier: 4.5.1 version: 4.5.1 @@ -2278,16 +2284,8 @@ packages: resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.26.5': - resolution: {integrity: sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==} - engines: {node: '>=6.9.0'} - - '@babel/compat-data@7.27.3': - resolution: {integrity: sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.26.7': - resolution: {integrity: sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==} + '@babel/compat-data@7.27.5': + resolution: {integrity: sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==} engines: {node: '>=6.9.0'} '@babel/core@7.27.3': @@ -2298,8 +2296,8 @@ packages: resolution: {integrity: sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==} engines: {node: '>=6.9.0'} - '@babel/generator@7.27.3': - resolution: {integrity: sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==} + '@babel/generator@7.27.5': + resolution: {integrity: sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==} engines: {node: '>=6.9.0'} '@babel/helper-annotate-as-pure@7.25.9': @@ -2310,10 +2308,6 @@ packages: resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.26.5': - resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} - engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.27.2': resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} @@ -2368,12 +2362,6 @@ packages: resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.26.0': - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - '@babel/helper-module-transforms@7.27.3': resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} engines: {node: '>=6.9.0'} @@ -2438,10 +2426,6 @@ packages: resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.25.9': - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.27.1': resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} @@ -2450,12 +2434,8 @@ packages: resolution: {integrity: sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.26.7': - resolution: {integrity: sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.27.3': - resolution: {integrity: sha512-h/eKy9agOya1IGuLaZ9tEUgz+uIRXcbtOhRtUyyMf8JFmn1iT13vnl/IGVWSkdOCG/pC57U4S1jnAabAavTMwg==} + '@babel/helpers@7.27.4': + resolution: {integrity: sha512-Y+bO6U+I7ZKaM5G5rDUZiYfUvQPUibYmAFe7EnKdnKBbVXDZxvp+MWOH5gYciY0EPk4EScsuFMQBbEfpdRKSCQ==} engines: {node: '>=6.9.0'} '@babel/parser@7.26.7': @@ -2463,8 +2443,8 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/parser@7.27.3': - resolution: {integrity: sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==} + '@babel/parser@7.27.5': + resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==} engines: {node: '>=6.0.0'} hasBin: true @@ -2656,8 +2636,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoping@7.27.3': - resolution: {integrity: sha512-+F8CnfhuLhwUACIJMLWnjz6zvzYM2r0yeIHKlbgfw7ml8rOMJsXNXV/hyRcb3nb493gRs4WvYpQAndWj/qQmkQ==} + '@babel/plugin-transform-block-scoping@7.27.5': + resolution: {integrity: sha512-JF6uE2s67f0y2RZcm2kpAUEbD50vH62TyWVebxwHAlbSdM49VqPz8t4a1uIjp4NIOIZ4xzLfjY5emt/RCyC7TQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2884,8 +2864,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regenerator@7.27.1': - resolution: {integrity: sha512-B19lbbL7PMrKr52BNPjCqg1IyNUIjTcxKj8uX9zHO+PmWN93s19NDr/f69mIkEp2x9nmDJ08a7lgHaTTzvW7mw==} + '@babel/plugin-transform-regenerator@7.27.5': + resolution: {integrity: sha512-uhB8yHerfe3MWnuLAhEbeQ4afVoqv8BQsPqrTv7e/jZ9y00kJL6l9a/f4OWaKxotmjzewfEyXE1vgDJenkQ2/Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -3001,8 +2981,8 @@ packages: resolution: {integrity: sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.27.3': - resolution: {integrity: sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ==} + '@babel/traverse@7.27.4': + resolution: {integrity: sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==} engines: {node: '>=6.9.0'} '@babel/types@7.26.7': @@ -3853,33 +3833,65 @@ packages: cjs-module-lexer: optional: true + '@img/sharp-darwin-arm64@0.33.5': + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + '@img/sharp-darwin-arm64@0.34.1': resolution: {integrity: sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [darwin] + '@img/sharp-darwin-x64@0.33.5': + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + '@img/sharp-darwin-x64@0.34.1': resolution: {integrity: sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [darwin] + '@img/sharp-libvips-darwin-arm64@1.0.4': + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} + cpu: [arm64] + os: [darwin] + '@img/sharp-libvips-darwin-arm64@1.1.0': resolution: {integrity: sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==} cpu: [arm64] os: [darwin] + '@img/sharp-libvips-darwin-x64@1.0.4': + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} + cpu: [x64] + os: [darwin] + '@img/sharp-libvips-darwin-x64@1.1.0': resolution: {integrity: sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==} cpu: [x64] os: [darwin] + '@img/sharp-libvips-linux-arm64@1.0.4': + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} + cpu: [arm64] + os: [linux] + '@img/sharp-libvips-linux-arm64@1.1.0': resolution: {integrity: sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==} cpu: [arm64] os: [linux] + '@img/sharp-libvips-linux-arm@1.0.5': + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} + cpu: [arm] + os: [linux] + '@img/sharp-libvips-linux-arm@1.1.0': resolution: {integrity: sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==} cpu: [arm] @@ -3890,73 +3902,146 @@ packages: cpu: [ppc64] os: [linux] + '@img/sharp-libvips-linux-s390x@1.0.4': + resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} + cpu: [s390x] + os: [linux] + '@img/sharp-libvips-linux-s390x@1.1.0': resolution: {integrity: sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==} cpu: [s390x] os: [linux] + '@img/sharp-libvips-linux-x64@1.0.4': + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} + cpu: [x64] + os: [linux] + '@img/sharp-libvips-linux-x64@1.1.0': resolution: {integrity: sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==} cpu: [x64] os: [linux] + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} + cpu: [arm64] + os: [linux] + '@img/sharp-libvips-linuxmusl-arm64@1.1.0': resolution: {integrity: sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==} cpu: [arm64] os: [linux] + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} + cpu: [x64] + os: [linux] + '@img/sharp-libvips-linuxmusl-x64@1.1.0': resolution: {integrity: sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==} cpu: [x64] os: [linux] + '@img/sharp-linux-arm64@0.33.5': + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + '@img/sharp-linux-arm64@0.34.1': resolution: {integrity: sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + '@img/sharp-linux-arm@0.33.5': + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + '@img/sharp-linux-arm@0.34.1': resolution: {integrity: sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] + '@img/sharp-linux-s390x@0.33.5': + resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + '@img/sharp-linux-s390x@0.34.1': resolution: {integrity: sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] + '@img/sharp-linux-x64@0.33.5': + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + '@img/sharp-linux-x64@0.34.1': resolution: {integrity: sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + '@img/sharp-linuxmusl-arm64@0.33.5': + resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + '@img/sharp-linuxmusl-arm64@0.34.1': resolution: {integrity: sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + '@img/sharp-linuxmusl-x64@0.33.5': + resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + '@img/sharp-linuxmusl-x64@0.34.1': resolution: {integrity: sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + '@img/sharp-wasm32@0.33.5': + resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + '@img/sharp-wasm32@0.34.1': resolution: {integrity: sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [wasm32] + '@img/sharp-win32-ia32@0.33.5': + resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + '@img/sharp-win32-ia32@0.34.1': resolution: {integrity: sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ia32] os: [win32] + '@img/sharp-win32-x64@0.33.5': + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + '@img/sharp-win32-x64@0.34.1': resolution: {integrity: sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -4334,8 +4419,8 @@ packages: '@next/env@15.2.0': resolution: {integrity: sha512-eMgJu1RBXxxqqnuRJQh5RozhskoNUDHBFybvi+Z+yK9qzKeG7dadhv/Vp1YooSZmCnegf7JxWuapV77necLZNA==} - '@next/env@15.3.0': - resolution: {integrity: sha512-6mDmHX24nWlHOlbwUiAOmMyY7KELimmi+ed8qWcJYjqXeC+G6JzPZ3QosOAfjNwgMIzwhXBiRiCgdh8axTTdTA==} + '@next/env@15.2.3': + resolution: {integrity: sha512-a26KnbW9DFEUsSxAxKBORR/uD9THoYoKbkpFywMN/AFvboTt94b8+g/07T8J6ACsdLag8/PDU60ov4rPxRAixw==} '@next/env@15.3.2': resolution: {integrity: sha512-xURk++7P7qR9JG1jJtLzPzf0qEvqCN0A/T3DXf8IPMKo9/6FfjxtEffRJIIew/bIL4T3C2jLLqBor8B/zVlx6g==} @@ -4343,8 +4428,8 @@ packages: '@next/eslint-plugin-next@15.3.2': resolution: {integrity: sha512-ijVRTXBgnHT33aWnDtmlG+LJD+5vhc9AKTJPquGG5NKXjpKNjc62woIhFtrAcWdBobt8kqjCoaJ0q6sDQoX7aQ==} - '@next/swc-darwin-arm64@15.3.0': - resolution: {integrity: sha512-PDQcByT0ZfF2q7QR9d+PNj3wlNN4K6Q8JoHMwFyk252gWo4gKt7BF8Y2+KBgDjTFBETXZ/TkBEUY7NIIY7A/Kw==} + '@next/swc-darwin-arm64@15.2.3': + resolution: {integrity: sha512-uaBhA8aLbXLqwjnsHSkxs353WrRgQgiFjduDpc7YXEU0B54IKx3vU+cxQlYwPCyC8uYEEX7THhtQQsfHnvv8dw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -4355,8 +4440,8 @@ packages: cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.3.0': - resolution: {integrity: sha512-m+eO21yg80En8HJ5c49AOQpFDq+nP51nu88ZOMCorvw3g//8g1JSUsEiPSiFpJo1KCTQ+jm9H0hwXK49H/RmXg==} + '@next/swc-darwin-x64@15.2.3': + resolution: {integrity: sha512-pVwKvJ4Zk7h+4hwhqOUuMx7Ib02u3gDX3HXPKIShBi9JlYllI0nU6TWLbPT94dt7FSi6mSBhfc2JrHViwqbOdw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -4367,8 +4452,8 @@ packages: cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.3.0': - resolution: {integrity: sha512-H0Kk04ZNzb6Aq/G6e0un4B3HekPnyy6D+eUBYPJv9Abx8KDYgNMWzKt4Qhj57HXV3sTTjsfc1Trc1SxuhQB+Tg==} + '@next/swc-linux-arm64-gnu@15.2.3': + resolution: {integrity: sha512-50ibWdn2RuFFkOEUmo9NCcQbbV9ViQOrUfG48zHBCONciHjaUKtHcYFiCwBVuzD08fzvzkWuuZkd4AqbvKO7UQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -4379,8 +4464,8 @@ packages: cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.3.0': - resolution: {integrity: sha512-k8GVkdMrh/+J9uIv/GpnHakzgDQhrprJ/FbGQvwWmstaeFG06nnAoZCJV+wO/bb603iKV1BXt4gHG+s2buJqZA==} + '@next/swc-linux-arm64-musl@15.2.3': + resolution: {integrity: sha512-2gAPA7P652D3HzR4cLyAuVYwYqjG0mt/3pHSWTCyKZq/N/dJcUAEoNQMyUmwTZWCJRKofB+JPuDVP2aD8w2J6Q==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -4391,8 +4476,8 @@ packages: cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.3.0': - resolution: {integrity: sha512-ZMQ9yzDEts/vkpFLRAqfYO1wSpIJGlQNK9gZ09PgyjBJUmg8F/bb8fw2EXKgEaHbCc4gmqMpDfh+T07qUphp9A==} + '@next/swc-linux-x64-gnu@15.2.3': + resolution: {integrity: sha512-ODSKvrdMgAJOVU4qElflYy1KSZRM3M45JVbeZu42TINCMG3anp7YCBn80RkISV6bhzKwcUqLBAmOiWkaGtBA9w==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -4403,8 +4488,8 @@ packages: cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.3.0': - resolution: {integrity: sha512-RFwq5VKYTw9TMr4T3e5HRP6T4RiAzfDJ6XsxH8j/ZeYq2aLsBqCkFzwMI0FmnSsLaUbOb46Uov0VvN3UciHX5A==} + '@next/swc-linux-x64-musl@15.2.3': + resolution: {integrity: sha512-ZR9kLwCWrlYxwEoytqPi1jhPd1TlsSJWAc+H/CJHmHkf2nD92MQpSRIURR1iNgA/kuFSdxB8xIPt4p/T78kwsg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -4415,8 +4500,8 @@ packages: cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.3.0': - resolution: {integrity: sha512-a7kUbqa/k09xPjfCl0RSVAvEjAkYBYxUzSVAzk2ptXiNEL+4bDBo9wNC43G/osLA/EOGzG4CuNRFnQyIHfkRgQ==} + '@next/swc-win32-arm64-msvc@15.2.3': + resolution: {integrity: sha512-+G2FrDcfm2YDbhDiObDU/qPriWeiz/9cRR0yMWJeTLGGX6/x8oryO3tt7HhodA1vZ8r2ddJPCjtLcpaVl7TE2Q==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -4427,8 +4512,8 @@ packages: cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.3.0': - resolution: {integrity: sha512-vHUQS4YVGJPmpjn7r5lEZuMhK5UQBNBRSB+iGDvJjaNk649pTIcRluDWNb9siunyLLiu/LDPHfvxBtNamyuLTw==} + '@next/swc-win32-x64-msvc@15.2.3': + resolution: {integrity: sha512-gHYS9tc+G2W0ZC8rBL+H6RdtXIyk40uLiaos0yj5US85FNhbFEndMA2nW3z47nzOWiSvXTZ5kBClc3rD0zJg0w==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -6738,8 +6823,8 @@ packages: effect@3.10.3: resolution: {integrity: sha512-+Z5bUhzTeqYlfoPsfXMZG1pYadqLBKARD3xwMIoEAESsOhKFOrUsHHNCy2ZZW3/6oa4wokgT01k1zavA4BAQ4w==} - electron-to-chromium@1.5.161: - resolution: {integrity: sha512-hwtetwfKNZo/UlwHIVBlKZVdy7o8bIZxxKs0Mv/ROPiQQQmDgdm5a+KvKtBsxM8ZjFzTaCeLoodZ8jiBE3o9rA==} + electron-to-chromium@1.5.162: + resolution: {integrity: sha512-hQA+Zb5QQwoSaXJWEAGEw1zhk//O7qDzib05Z4qTqZfNju/FAkrm5ZInp0JbTp4Z18A6bilopdZWEYrFSsfllA==} electron-to-chromium@1.5.53: resolution: {integrity: sha512-7F6qFMWzBArEFK4PLE+c+nWzhS1kIoNkQvGnNDogofxQAym+roQ0GUIdw6C/4YdJ6JKGp19c2a/DLcfKTi4wRQ==} @@ -7652,6 +7737,10 @@ packages: resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} engines: {node: '>= 12'} + ipaddr.js@2.2.0: + resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} + engines: {node: '>= 10'} + is-alphabetical@2.0.1: resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} @@ -8547,8 +8636,8 @@ packages: resolution: {integrity: sha512-lDcBsjBSMlj3LXH2v/FW3txlh2pYTjmbOXPYJD93HI5EwuLzI11tdHSIpUMmfq/IOsldj4Ps8M8flhm+pCK4Ew==} engines: {node: '>=12.22.0'} - next@15.3.0: - resolution: {integrity: sha512-k0MgP6BsK8cZ73wRjMazl2y2UcXj49ZXLDEgx6BikWuby/CN+nh81qFFI16edgd7xYpe/jj2OZEIwCoqnzz0bQ==} + next@15.2.3: + resolution: {integrity: sha512-x6eDkZxk2rPpu46E1ZVUWIBhYCLszmUY6fvHBFcbzJ9dD+qRX6vcHusaqqDlnY+VngKzKbAiG2iRCkPbmi8f7w==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: @@ -9557,6 +9646,10 @@ packages: resolution: {integrity: sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==} engines: {node: '>=14.15.0'} + sharp@0.33.5: + resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + sharp@0.34.1: resolution: {integrity: sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -10193,6 +10286,10 @@ packages: resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} engines: {node: '>=14.0'} + undici@7.10.0: + resolution: {integrity: sha512-u5otvFBOBZvmdjWLVW+5DAc9Nkq8f24g0O9oY7qw2JVIF1VocIFoyz9JFkuVOS2j41AufeO0xnlweJ2RLT8nGw==} + engines: {node: '>=20.18.1'} + unfetch@4.2.0: resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} @@ -11346,41 +11443,19 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.26.5': {} - - '@babel/compat-data@7.27.3': {} - - '@babel/core@7.26.7': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.5 - '@babel/helper-compilation-targets': 7.26.5 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.7) - '@babel/helpers': 7.26.7 - '@babel/parser': 7.26.7 - '@babel/template': 7.25.9 - '@babel/traverse': 7.26.7 - '@babel/types': 7.26.7 - convert-source-map: 2.0.0 - debug: 4.3.7 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color + '@babel/compat-data@7.27.5': {} '@babel/core@7.27.3': dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.27.1 - '@babel/generator': 7.27.3 + '@babel/generator': 7.27.5 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.3) - '@babel/helpers': 7.27.3 - '@babel/parser': 7.27.3 + '@babel/helpers': 7.27.4 + '@babel/parser': 7.27.5 '@babel/template': 7.27.2 - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 '@babel/types': 7.27.3 convert-source-map: 2.0.0 debug: 4.3.7 @@ -11398,9 +11473,9 @@ snapshots: '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.0.2 - '@babel/generator@7.27.3': + '@babel/generator@7.27.5': dependencies: - '@babel/parser': 7.27.3 + '@babel/parser': 7.27.5 '@babel/types': 7.27.3 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 @@ -11414,29 +11489,21 @@ snapshots: dependencies: '@babel/types': 7.27.3 - '@babel/helper-compilation-targets@7.26.5': - dependencies: - '@babel/compat-data': 7.26.5 - '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.2 - lru-cache: 5.1.1 - semver: 6.3.1 - '@babel/helper-compilation-targets@7.27.2': dependencies: - '@babel/compat-data': 7.27.3 + '@babel/compat-data': 7.27.5 '@babel/helper-validator-option': 7.27.1 browserslist: 4.24.2 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.26.7)': + '@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.27.3)': dependencies: - '@babel/core': 7.26.7 + '@babel/core': 7.27.3 '@babel/helper-annotate-as-pure': 7.25.9 '@babel/helper-member-expression-to-functions': 7.25.9 '@babel/helper-optimise-call-expression': 7.25.9 - '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.7) + '@babel/helper-replace-supers': 7.25.9(@babel/core@7.27.3) '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 '@babel/traverse': 7.26.7 semver: 6.3.1 @@ -11451,7 +11518,7 @@ snapshots: '@babel/helper-optimise-call-expression': 7.27.1 '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.3) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -11501,7 +11568,7 @@ snapshots: '@babel/helper-member-expression-to-functions@7.27.1': dependencies: - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 '@babel/types': 7.27.3 transitivePeerDependencies: - supports-color @@ -11515,26 +11582,17 @@ snapshots: '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 '@babel/types': 7.27.3 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.7)': - dependencies: - '@babel/core': 7.26.7 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.7 - transitivePeerDependencies: - - supports-color - '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.3)': dependencies: '@babel/core': 7.27.3 '@babel/helper-module-imports': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 transitivePeerDependencies: - supports-color @@ -11555,13 +11613,13 @@ snapshots: '@babel/core': 7.27.3 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-wrap-function': 7.27.1 - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 transitivePeerDependencies: - supports-color - '@babel/helper-replace-supers@7.25.9(@babel/core@7.26.7)': + '@babel/helper-replace-supers@7.25.9(@babel/core@7.27.3)': dependencies: - '@babel/core': 7.26.7 + '@babel/core': 7.27.3 '@babel/helper-member-expression-to-functions': 7.25.9 '@babel/helper-optimise-call-expression': 7.25.9 '@babel/traverse': 7.26.7 @@ -11573,7 +11631,7 @@ snapshots: '@babel/core': 7.27.3 '@babel/helper-member-expression-to-functions': 7.27.1 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 transitivePeerDependencies: - supports-color @@ -11586,7 +11644,7 @@ snapshots: '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 '@babel/types': 7.27.3 transitivePeerDependencies: - supports-color @@ -11599,24 +11657,17 @@ snapshots: '@babel/helper-validator-identifier@7.27.1': {} - '@babel/helper-validator-option@7.25.9': {} - '@babel/helper-validator-option@7.27.1': {} '@babel/helper-wrap-function@7.27.1': dependencies: '@babel/template': 7.27.2 - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 '@babel/types': 7.27.3 transitivePeerDependencies: - supports-color - '@babel/helpers@7.26.7': - dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.7 - - '@babel/helpers@7.27.3': + '@babel/helpers@7.27.4': dependencies: '@babel/template': 7.27.2 '@babel/types': 7.27.3 @@ -11625,7 +11676,7 @@ snapshots: dependencies: '@babel/types': 7.26.7 - '@babel/parser@7.27.3': + '@babel/parser@7.27.5': dependencies: '@babel/types': 7.27.3 @@ -11633,7 +11684,7 @@ snapshots: dependencies: '@babel/core': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 transitivePeerDependencies: - supports-color @@ -11660,14 +11711,14 @@ snapshots: dependencies: '@babel/core': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 transitivePeerDependencies: - supports-color - '@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.26.7)': + '@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.27.3)': dependencies: - '@babel/core': 7.26.7 - '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.7) + '@babel/core': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.27.3) '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color @@ -11797,7 +11848,7 @@ snapshots: '@babel/core': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.27.3) - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 transitivePeerDependencies: - supports-color @@ -11815,7 +11866,7 @@ snapshots: '@babel/core': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-block-scoping@7.27.3(@babel/core@7.27.3)': + '@babel/plugin-transform-block-scoping@7.27.5(@babel/core@7.27.3)': dependencies: '@babel/core': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 @@ -11843,7 +11894,7 @@ snapshots: '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.3) - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -11904,7 +11955,7 @@ snapshots: '@babel/core': 7.27.3 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 transitivePeerDependencies: - supports-color @@ -11950,7 +12001,7 @@ snapshots: '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.3) '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.27.3 + '@babel/traverse': 7.27.4 transitivePeerDependencies: - supports-color @@ -12068,7 +12119,7 @@ snapshots: '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-regenerator@7.27.1(@babel/core@7.27.3)': + '@babel/plugin-transform-regenerator@7.27.5(@babel/core@7.27.3)': dependencies: '@babel/core': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 @@ -12148,7 +12199,7 @@ snapshots: '@babel/preset-env@7.27.2(@babel/core@7.27.3)': dependencies: - '@babel/compat-data': 7.27.3 + '@babel/compat-data': 7.27.5 '@babel/core': 7.27.3 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 @@ -12166,7 +12217,7 @@ snapshots: '@babel/plugin-transform-async-generator-functions': 7.27.1(@babel/core@7.27.3) '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.27.3) '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.27.3) - '@babel/plugin-transform-block-scoping': 7.27.3(@babel/core@7.27.3) + '@babel/plugin-transform-block-scoping': 7.27.5(@babel/core@7.27.3) '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.27.3) '@babel/plugin-transform-class-static-block': 7.27.1(@babel/core@7.27.3) '@babel/plugin-transform-classes': 7.27.1(@babel/core@7.27.3) @@ -12200,7 +12251,7 @@ snapshots: '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.27.3) '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.27.3) '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.27.3) - '@babel/plugin-transform-regenerator': 7.27.1(@babel/core@7.27.3) + '@babel/plugin-transform-regenerator': 7.27.5(@babel/core@7.27.3) '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.27.3) '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.27.3) '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.27.3) @@ -12264,7 +12315,7 @@ snapshots: '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.27.3 + '@babel/parser': 7.27.5 '@babel/types': 7.27.3 '@babel/traverse@7.26.7': @@ -12279,11 +12330,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/traverse@7.27.3': + '@babel/traverse@7.27.4': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.27.3 - '@babel/parser': 7.27.3 + '@babel/generator': 7.27.5 + '@babel/parser': 7.27.5 '@babel/template': 7.27.2 '@babel/types': 7.27.3 debug: 4.3.7 @@ -12971,81 +13022,156 @@ snapshots: optionalDependencies: cjs-module-lexer: 1.4.1 + '@img/sharp-darwin-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.4 + optional: true + '@img/sharp-darwin-arm64@0.34.1': optionalDependencies: '@img/sharp-libvips-darwin-arm64': 1.1.0 optional: true + '@img/sharp-darwin-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.4 + optional: true + '@img/sharp-darwin-x64@0.34.1': optionalDependencies: '@img/sharp-libvips-darwin-x64': 1.1.0 optional: true + '@img/sharp-libvips-darwin-arm64@1.0.4': + optional: true + '@img/sharp-libvips-darwin-arm64@1.1.0': optional: true + '@img/sharp-libvips-darwin-x64@1.0.4': + optional: true + '@img/sharp-libvips-darwin-x64@1.1.0': optional: true + '@img/sharp-libvips-linux-arm64@1.0.4': + optional: true + '@img/sharp-libvips-linux-arm64@1.1.0': optional: true + '@img/sharp-libvips-linux-arm@1.0.5': + optional: true + '@img/sharp-libvips-linux-arm@1.1.0': optional: true '@img/sharp-libvips-linux-ppc64@1.1.0': optional: true + '@img/sharp-libvips-linux-s390x@1.0.4': + optional: true + '@img/sharp-libvips-linux-s390x@1.1.0': optional: true + '@img/sharp-libvips-linux-x64@1.0.4': + optional: true + '@img/sharp-libvips-linux-x64@1.1.0': optional: true + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + optional: true + '@img/sharp-libvips-linuxmusl-arm64@1.1.0': optional: true + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + optional: true + '@img/sharp-libvips-linuxmusl-x64@1.1.0': optional: true + '@img/sharp-linux-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.4 + optional: true + '@img/sharp-linux-arm64@0.34.1': optionalDependencies: '@img/sharp-libvips-linux-arm64': 1.1.0 optional: true + '@img/sharp-linux-arm@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.5 + optional: true + '@img/sharp-linux-arm@0.34.1': optionalDependencies: '@img/sharp-libvips-linux-arm': 1.1.0 optional: true + '@img/sharp-linux-s390x@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.4 + optional: true + '@img/sharp-linux-s390x@0.34.1': optionalDependencies: '@img/sharp-libvips-linux-s390x': 1.1.0 optional: true + '@img/sharp-linux-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.4 + optional: true + '@img/sharp-linux-x64@0.34.1': optionalDependencies: '@img/sharp-libvips-linux-x64': 1.1.0 optional: true + '@img/sharp-linuxmusl-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + optional: true + '@img/sharp-linuxmusl-arm64@0.34.1': optionalDependencies: '@img/sharp-libvips-linuxmusl-arm64': 1.1.0 optional: true + '@img/sharp-linuxmusl-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + optional: true + '@img/sharp-linuxmusl-x64@0.34.1': optionalDependencies: '@img/sharp-libvips-linuxmusl-x64': 1.1.0 optional: true + '@img/sharp-wasm32@0.33.5': + dependencies: + '@emnapi/runtime': 1.4.1 + optional: true + '@img/sharp-wasm32@0.34.1': dependencies: '@emnapi/runtime': 1.4.1 optional: true + '@img/sharp-win32-ia32@0.33.5': + optional: true + '@img/sharp-win32-ia32@0.34.1': optional: true + '@img/sharp-win32-x64@0.33.5': + optional: true + '@img/sharp-win32-x64@0.34.1': optional: true @@ -13578,7 +13704,7 @@ snapshots: '@next/env@15.2.0': {} - '@next/env@15.3.0': {} + '@next/env@15.2.3': {} '@next/env@15.3.2': {} @@ -13586,49 +13712,49 @@ snapshots: dependencies: fast-glob: 3.3.1 - '@next/swc-darwin-arm64@15.3.0': + '@next/swc-darwin-arm64@15.2.3': optional: true '@next/swc-darwin-arm64@15.3.2': optional: true - '@next/swc-darwin-x64@15.3.0': + '@next/swc-darwin-x64@15.2.3': optional: true '@next/swc-darwin-x64@15.3.2': optional: true - '@next/swc-linux-arm64-gnu@15.3.0': + '@next/swc-linux-arm64-gnu@15.2.3': optional: true '@next/swc-linux-arm64-gnu@15.3.2': optional: true - '@next/swc-linux-arm64-musl@15.3.0': + '@next/swc-linux-arm64-musl@15.2.3': optional: true '@next/swc-linux-arm64-musl@15.3.2': optional: true - '@next/swc-linux-x64-gnu@15.3.0': + '@next/swc-linux-x64-gnu@15.2.3': optional: true '@next/swc-linux-x64-gnu@15.3.2': optional: true - '@next/swc-linux-x64-musl@15.3.0': + '@next/swc-linux-x64-musl@15.2.3': optional: true '@next/swc-linux-x64-musl@15.3.2': optional: true - '@next/swc-win32-arm64-msvc@15.3.0': + '@next/swc-win32-arm64-msvc@15.2.3': optional: true '@next/swc-win32-arm64-msvc@15.3.2': optional: true - '@next/swc-win32-x64-msvc@15.3.0': + '@next/swc-win32-x64-msvc@15.2.3': optional: true '@next/swc-win32-x64-msvc@15.3.2': @@ -15715,7 +15841,7 @@ snapshots: babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.27.3): dependencies: - '@babel/compat-data': 7.27.3 + '@babel/compat-data': 7.27.5 '@babel/core': 7.27.3 '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.27.3) semver: 6.3.1 @@ -15847,7 +15973,7 @@ snapshots: browserslist@4.25.0: dependencies: caniuse-lite: 1.0.30001720 - electron-to-chromium: 1.5.161 + electron-to-chromium: 1.5.162 node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.25.0) @@ -16399,7 +16525,7 @@ snapshots: dependencies: fast-check: 3.23.1 - electron-to-chromium@1.5.161: {} + electron-to-chromium@1.5.162: {} electron-to-chromium@1.5.53: {} @@ -16722,9 +16848,9 @@ snapshots: eslint-plugin-react-compiler@19.1.0-rc.2(eslint@9.22.0(jiti@1.21.6)): dependencies: - '@babel/core': 7.26.7 + '@babel/core': 7.27.3 '@babel/parser': 7.26.7 - '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.26.7) + '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.27.3) eslint: 9.22.0(jiti@1.21.6) hermes-parser: 0.25.1 zod: 3.23.8 @@ -17587,6 +17713,8 @@ snapshots: sprintf-js: 1.1.3 optional: true + ipaddr.js@2.2.0: {} + is-alphabetical@2.0.1: {} is-alphanumerical@2.0.1: @@ -17758,7 +17886,7 @@ snapshots: '@babel/parser': 7.26.7 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.6.3 + semver: 7.7.1 transitivePeerDependencies: - supports-color @@ -18783,9 +18911,9 @@ snapshots: transitivePeerDependencies: - supports-color - next@15.3.0(@babel/core@7.27.3)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.77.4): + next@15.2.3(@babel/core@7.27.3)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.77.4): dependencies: - '@next/env': 15.3.0 + '@next/env': 15.2.3 '@swc/counter': 0.1.3 '@swc/helpers': 0.5.15 busboy: 1.6.0 @@ -18795,19 +18923,19 @@ snapshots: react-dom: 19.1.0(react@19.1.0) styled-jsx: 5.1.6(@babel/core@7.27.3)(babel-plugin-macros@3.1.0)(react@19.1.0) optionalDependencies: - '@next/swc-darwin-arm64': 15.3.0 - '@next/swc-darwin-x64': 15.3.0 - '@next/swc-linux-arm64-gnu': 15.3.0 - '@next/swc-linux-arm64-musl': 15.3.0 - '@next/swc-linux-x64-gnu': 15.3.0 - '@next/swc-linux-x64-musl': 15.3.0 - '@next/swc-win32-arm64-msvc': 15.3.0 - '@next/swc-win32-x64-msvc': 15.3.0 + '@next/swc-darwin-arm64': 15.2.3 + '@next/swc-darwin-x64': 15.2.3 + '@next/swc-linux-arm64-gnu': 15.2.3 + '@next/swc-linux-arm64-musl': 15.2.3 + '@next/swc-linux-x64-gnu': 15.2.3 + '@next/swc-linux-x64-musl': 15.2.3 + '@next/swc-win32-arm64-msvc': 15.2.3 + '@next/swc-win32-x64-msvc': 15.2.3 '@opentelemetry/api': 1.9.0 '@playwright/test': 1.50.0 babel-plugin-react-compiler: 19.1.0-rc.2 sass: 1.77.4 - sharp: 0.34.1 + sharp: 0.33.5 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -18843,7 +18971,7 @@ snapshots: node-abi@3.71.0: dependencies: - semver: 7.6.3 + semver: 7.7.1 node-addon-api@6.1.0: {} @@ -19814,11 +19942,38 @@ snapshots: detect-libc: 2.0.3 node-addon-api: 6.1.0 prebuild-install: 7.1.2 - semver: 7.6.3 + semver: 7.7.1 simple-get: 4.0.1 tar-fs: 3.0.6 tunnel-agent: 0.6.0 + sharp@0.33.5: + dependencies: + color: 4.2.3 + detect-libc: 2.0.3 + semver: 7.7.1 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-libvips-darwin-arm64': 1.0.4 + '@img/sharp-libvips-darwin-x64': 1.0.4 + '@img/sharp-libvips-linux-arm': 1.0.5 + '@img/sharp-libvips-linux-arm64': 1.0.4 + '@img/sharp-libvips-linux-s390x': 1.0.4 + '@img/sharp-libvips-linux-x64': 1.0.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-s390x': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-linuxmusl-arm64': 0.33.5 + '@img/sharp-linuxmusl-x64': 0.33.5 + '@img/sharp-wasm32': 0.33.5 + '@img/sharp-win32-ia32': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 + optional: true + sharp@0.34.1: dependencies: color: 4.2.3 @@ -20511,6 +20666,8 @@ snapshots: dependencies: '@fastify/busboy': 2.1.1 + undici@7.10.0: {} + unfetch@4.2.0: {} unicode-canonical-property-names-ecmascript@2.0.1: {} diff --git a/test/uploads/config.ts b/test/uploads/config.ts index cf569014a..2751266e3 100644 --- a/test/uploads/config.ts +++ b/test/uploads/config.ts @@ -16,6 +16,7 @@ import { CustomUploadFieldCollection } from './collections/CustomUploadField/ind import { Uploads1 } from './collections/Upload1/index.js' import { Uploads2 } from './collections/Upload2/index.js' import { + allowListMediaSlug, animatedTypeMedia, audioSlug, customFileNameMediaSlug, @@ -405,6 +406,27 @@ export default buildConfigWithDefaults({ pasteURL: false, }, }, + { + slug: allowListMediaSlug, + fields: [], + upload: { + pasteURL: { + allowList: [ + { protocol: 'http', hostname: '127.0.0.1', port: '', search: '' }, + { protocol: 'http', hostname: 'localhost', port: '', search: '' }, + { protocol: 'http', hostname: '[::1]', port: '', search: '' }, + { protocol: 'http', hostname: '10.0.0.1', port: '', search: '' }, + { protocol: 'http', hostname: '192.168.1.1', port: '', search: '' }, + { protocol: 'http', hostname: '172.16.0.1', port: '', search: '' }, + { protocol: 'http', hostname: '169.254.1.1', port: '', search: '' }, + { protocol: 'http', hostname: '224.0.0.1', port: '', search: '' }, + { protocol: 'http', hostname: '0.0.0.0', port: '', search: '' }, + { protocol: 'http', hostname: '255.255.255.255', port: '', search: '' }, + ], + }, + staticDir: path.resolve(dirname, './media'), + }, + }, { slug: animatedTypeMedia, fields: [], diff --git a/test/uploads/int.spec.ts b/test/uploads/int.spec.ts index e7ba4d54a..f50eb79da 100644 --- a/test/uploads/int.spec.ts +++ b/test/uploads/int.spec.ts @@ -12,6 +12,7 @@ import type { Enlarge, Media } from './payload-types.js' import { initPayloadInt } from '../helpers/initPayloadInt.js' import { createStreamableFile } from './createStreamableFile.js' import { + allowListMediaSlug, enlargeSlug, focalNoSizesSlug, focalOnlySlug, @@ -543,6 +544,48 @@ describe('Collections - Uploads', () => { expect(doc.docs[0].image).toBeFalsy() }) }) + + describe('filters', () => { + it.each` + url | collection | errorContains + ${'http://127.0.0.1/file.png'} | ${mediaSlug} | ${'unsafe'} + ${'http://[::1]/file.png'} | ${mediaSlug} | ${'unsafe'} + ${'http://10.0.0.1/file.png'} | ${mediaSlug} | ${'unsafe'} + ${'http://192.168.1.1/file.png'} | ${mediaSlug} | ${'unsafe'} + ${'http://172.16.0.1/file.png'} | ${mediaSlug} | ${'unsafe'} + ${'http://169.254.1.1/file.png'} | ${mediaSlug} | ${'unsafe'} + ${'http://224.0.0.1/file.png'} | ${mediaSlug} | ${'unsafe'} + ${'http://0.0.0.0/file.png'} | ${mediaSlug} | ${'unsafe'} + ${'http://255.255.255.255/file.png'} | ${mediaSlug} | ${'unsafe'} + ${'http://127.0.0.1/file.png'} | ${allowListMediaSlug} | ${'There was a problem while uploading the file.'} + ${'http://[::1]/file.png'} | ${allowListMediaSlug} | ${'There was a problem while uploading the file.'} + ${'http://10.0.0.1/file.png'} | ${allowListMediaSlug} | ${'There was a problem while uploading the file.'} + ${'http://192.168.1.1/file.png'} | ${allowListMediaSlug} | ${'There was a problem while uploading the file.'} + ${'http://172.16.0.1/file.png'} | ${allowListMediaSlug} | ${'There was a problem while uploading the file.'} + ${'http://169.254.1.1/file.png'} | ${allowListMediaSlug} | ${'There was a problem while uploading the file.'} + ${'http://224.0.0.1/file.png'} | ${allowListMediaSlug} | ${'There was a problem while uploading the file.'} + ${'http://0.0.0.0/file.png'} | ${allowListMediaSlug} | ${'There was a problem while uploading the file.'} + ${'http://255.255.255.255/file.png'} | ${allowListMediaSlug} | ${'There was a problem while uploading the file.'} + `( + 'should block or filter uploading from $collection with URL: $url', + async ({ url, collection, errorContains }) => { + await expect( + payload.create({ + collection, + data: { + filename: 'test.png', + url, + }, + }), + ).rejects.toThrow( + expect.objectContaining({ + name: 'FileRetrievalError', + message: expect.stringContaining(errorContains), + }), + ) + }, + ) + }) }) describe('focal point', () => { diff --git a/test/uploads/payload-types.ts b/test/uploads/payload-types.ts index bddc9a5fa..bf730324c 100644 --- a/test/uploads/payload-types.ts +++ b/test/uploads/payload-types.ts @@ -80,6 +80,7 @@ export interface Config { 'focal-only': FocalOnly; 'focal-no-sizes': FocalNoSize; media: Media; + 'allow-list-media': AllowListMedia; 'animated-type-media': AnimatedTypeMedia; enlarge: Enlarge; 'without-enlarge': WithoutEnlarge; @@ -125,6 +126,7 @@ export interface Config { 'focal-only': FocalOnlySelect | FocalOnlySelect; 'focal-no-sizes': FocalNoSizesSelect | FocalNoSizesSelect; media: MediaSelect | MediaSelect; + 'allow-list-media': AllowListMediaSelect | AllowListMediaSelect; 'animated-type-media': AnimatedTypeMediaSelect | AnimatedTypeMediaSelect; enlarge: EnlargeSelect | EnlargeSelect; 'without-enlarge': WithoutEnlargeSelect | WithoutEnlargeSelect; @@ -732,6 +734,24 @@ export interface FocalNoSize { focalX?: number | null; focalY?: number | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "allow-list-media". + */ +export interface AllowListMedia { + id: string; + updatedAt: string; + createdAt: string; + url?: string | null; + thumbnailURL?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + focalX?: number | null; + focalY?: number | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "animated-type-media". @@ -1403,6 +1423,10 @@ export interface PayloadLockedDocument { relationTo: 'media'; value: string | Media; } | null) + | ({ + relationTo: 'allow-list-media'; + value: string | AllowListMedia; + } | null) | ({ relationTo: 'animated-type-media'; value: string | AnimatedTypeMedia; @@ -2123,6 +2147,23 @@ export interface MediaSelect { }; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "allow-list-media_select". + */ +export interface AllowListMediaSelect { + updatedAt?: T; + createdAt?: T; + url?: T; + thumbnailURL?: T; + filename?: T; + mimeType?: T; + filesize?: T; + width?: T; + height?: T; + focalX?: T; + focalY?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "animated-type-media_select". diff --git a/test/uploads/shared.ts b/test/uploads/shared.ts index f76b139f4..b271c7508 100644 --- a/test/uploads/shared.ts +++ b/test/uploads/shared.ts @@ -23,6 +23,7 @@ export const withMetadataSlug = 'with-meta-data' export const withoutMetadataSlug = 'without-meta-data' export const withOnlyJPEGMetadataSlug = 'with-only-jpeg-meta-data' export const customFileNameMediaSlug = 'custom-file-name-media' +export const allowListMediaSlug = 'allow-list-media' export const listViewPreviewSlug = 'list-view-preview' export const threeDimensionalSlug = 'three-dimensional'