payload 3.69.0-canary.9 → 3.69.0-internal.35bf893
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/operations/refresh.d.ts.map +1 -1
- package/dist/auth/operations/refresh.js +3 -2
- package/dist/auth/operations/refresh.js.map +1 -1
- package/dist/uploads/checkFileRestrictions.d.ts.map +1 -1
- package/dist/uploads/checkFileRestrictions.js +2 -26
- package/dist/uploads/checkFileRestrictions.js.map +1 -1
- package/dist/utilities/validateMimeType.d.ts.map +1 -1
- package/dist/utilities/validateMimeType.js +0 -3
- package/dist/utilities/validateMimeType.js.map +1 -1
- package/package.json +2 -2
- package/dist/uploads/validateSvg.d.ts +0 -6
- package/dist/uploads/validateSvg.d.ts.map +0 -1
- package/dist/uploads/validateSvg.js +0 -46
- package/dist/uploads/validateSvg.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../../src/auth/operations/refresh.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../../src/auth/operations/refresh.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAYpE,MAAM,MAAM,MAAM,GAAG;IACnB,GAAG,EAAE,MAAM,CAAA;IACX,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,QAAQ,CAAA;CACf,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,UAAU,EAAE,UAAU,CAAA;IACtB,GAAG,EAAE,cAAc,CAAA;CACpB,CAAA;AAED,eAAO,MAAM,gBAAgB,iBAAwB,SAAS,KAAG,OAAO,CAAC,MAAM,CAsK9E,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import url from 'url';
|
|
1
2
|
import { buildAfterOperation } from '../../collections/operations/utilities/buildAfterOperation.js';
|
|
2
3
|
import { buildBeforeOperation } from '../../collections/operations/utilities/buildBeforeOperation.js';
|
|
3
4
|
import { Forbidden } from '../../errors/index.js';
|
|
@@ -26,8 +27,8 @@ export const refreshOperation = async (incomingArgs)=>{
|
|
|
26
27
|
if (!args.req.user) {
|
|
27
28
|
throw new Forbidden(args.req.t);
|
|
28
29
|
}
|
|
29
|
-
const
|
|
30
|
-
const isGraphQL = pathname === config.routes.graphQL;
|
|
30
|
+
const parsedURL = url.parse(args.req.url);
|
|
31
|
+
const isGraphQL = parsedURL.pathname === config.routes.graphQL;
|
|
31
32
|
let user = await req.payload.db.findOne({
|
|
32
33
|
collection: collectionConfig.slug,
|
|
33
34
|
req,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/auth/operations/refresh.ts"],"sourcesContent":["import type { Collection } from '../../collections/config/types.js'\nimport type { Document, PayloadRequest } from '../../types/index.js'\n\nimport { buildAfterOperation } from '../../collections/operations/utilities/buildAfterOperation.js'\nimport { buildBeforeOperation } from '../../collections/operations/utilities/buildBeforeOperation.js'\nimport { Forbidden } from '../../errors/index.js'\nimport { commitTransaction } from '../../utilities/commitTransaction.js'\nimport { initTransaction } from '../../utilities/initTransaction.js'\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { getFieldsToSign } from '../getFieldsToSign.js'\nimport { jwtSign } from '../jwt.js'\nimport { removeExpiredSessions } from '../sessions.js'\n\nexport type Result = {\n exp: number\n refreshedToken: string\n setCookie?: boolean\n /** @deprecated\n * use:\n * ```ts\n * user._strategy\n * ```\n */\n strategy?: string\n user: Document\n}\n\nexport type Arguments = {\n collection: Collection\n req: PayloadRequest\n}\n\nexport const refreshOperation = async (incomingArgs: Arguments): Promise<Result> => {\n let args = incomingArgs\n\n try {\n const shouldCommit = await initTransaction(args.req)\n\n // /////////////////////////////////////\n // beforeOperation - Collection\n // /////////////////////////////////////\n\n args = await buildBeforeOperation({\n args,\n collection: args.collection.config,\n operation: 'refresh',\n })\n\n // /////////////////////////////////////\n // Refresh\n // /////////////////////////////////////\n\n const {\n collection: { config: collectionConfig },\n req,\n req: {\n payload: { config, secret },\n },\n } = args\n\n if (!args.req.user) {\n throw new Forbidden(args.req.t)\n }\n\n const
|
|
1
|
+
{"version":3,"sources":["../../../src/auth/operations/refresh.ts"],"sourcesContent":["import url from 'url'\n\nimport type { Collection } from '../../collections/config/types.js'\nimport type { Document, PayloadRequest } from '../../types/index.js'\n\nimport { buildAfterOperation } from '../../collections/operations/utilities/buildAfterOperation.js'\nimport { buildBeforeOperation } from '../../collections/operations/utilities/buildBeforeOperation.js'\nimport { Forbidden } from '../../errors/index.js'\nimport { commitTransaction } from '../../utilities/commitTransaction.js'\nimport { initTransaction } from '../../utilities/initTransaction.js'\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { getFieldsToSign } from '../getFieldsToSign.js'\nimport { jwtSign } from '../jwt.js'\nimport { removeExpiredSessions } from '../sessions.js'\n\nexport type Result = {\n exp: number\n refreshedToken: string\n setCookie?: boolean\n /** @deprecated\n * use:\n * ```ts\n * user._strategy\n * ```\n */\n strategy?: string\n user: Document\n}\n\nexport type Arguments = {\n collection: Collection\n req: PayloadRequest\n}\n\nexport const refreshOperation = async (incomingArgs: Arguments): Promise<Result> => {\n let args = incomingArgs\n\n try {\n const shouldCommit = await initTransaction(args.req)\n\n // /////////////////////////////////////\n // beforeOperation - Collection\n // /////////////////////////////////////\n\n args = await buildBeforeOperation({\n args,\n collection: args.collection.config,\n operation: 'refresh',\n })\n\n // /////////////////////////////////////\n // Refresh\n // /////////////////////////////////////\n\n const {\n collection: { config: collectionConfig },\n req,\n req: {\n payload: { config, secret },\n },\n } = args\n\n if (!args.req.user) {\n throw new Forbidden(args.req.t)\n }\n\n const parsedURL = url.parse(args.req.url!)\n const isGraphQL = parsedURL.pathname === config.routes.graphQL\n\n let user = await req.payload.db.findOne<any>({\n collection: collectionConfig.slug,\n req,\n where: { id: { equals: args.req.user.id } },\n })\n\n const sid = args.req.user._sid\n\n if (collectionConfig.auth.useSessions && !collectionConfig.auth.disableLocalStrategy) {\n if (!Array.isArray(user.sessions) || !sid) {\n throw new Forbidden(args.req.t)\n }\n\n const existingSession = user.sessions.find(({ id }: { id: number }) => id === sid)\n\n const now = new Date()\n const tokenExpInMs = collectionConfig.auth.tokenExpiration * 1000\n existingSession.expiresAt = new Date(now.getTime() + tokenExpInMs)\n\n // Prevent updatedAt from being updated when only refreshing a session\n user.updatedAt = null\n\n await req.payload.db.updateOne({\n id: user.id,\n collection: collectionConfig.slug,\n data: {\n ...user,\n sessions: removeExpiredSessions(user.sessions),\n },\n req,\n returning: false,\n })\n }\n\n user = await req.payload.findByID({\n id: user.id,\n collection: collectionConfig.slug,\n depth: isGraphQL ? 0 : args.collection.config.auth.depth,\n req: args.req,\n })\n\n if (user) {\n user.collection = args.req.user.collection\n user._strategy = args.req.user._strategy\n }\n\n let result!: Result\n\n // /////////////////////////////////////\n // refresh hook - Collection\n // /////////////////////////////////////\n\n for (const refreshHook of args.collection.config.hooks.refresh) {\n const hookResult = await refreshHook({ args, user })\n\n if (hookResult) {\n result = hookResult\n break\n }\n }\n\n if (!result) {\n const fieldsToSign = getFieldsToSign({\n collectionConfig,\n email: user?.email as string,\n sid,\n user: args?.req?.user,\n })\n\n const { exp, token: refreshedToken } = await jwtSign({\n fieldsToSign,\n secret,\n tokenExpiration: collectionConfig.auth.tokenExpiration,\n })\n\n result = {\n exp,\n refreshedToken,\n setCookie: true,\n /** @deprecated\n * use:\n * ```ts\n * user._strategy\n * ```\n */\n strategy: args.req.user._strategy,\n user,\n }\n }\n\n // /////////////////////////////////////\n // After Refresh - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.afterRefresh?.length) {\n for (const hook of collectionConfig.hooks.afterRefresh) {\n result =\n (await hook({\n collection: args.collection?.config,\n context: args.req.context,\n exp: result.exp,\n req: args.req,\n token: result.refreshedToken,\n })) || result\n }\n }\n\n // /////////////////////////////////////\n // afterOperation - Collection\n // /////////////////////////////////////\n\n result = await buildAfterOperation({\n args,\n collection: args.collection?.config,\n operation: 'refresh',\n result,\n })\n\n // /////////////////////////////////////\n // Return results\n // /////////////////////////////////////\n\n if (shouldCommit) {\n await commitTransaction(req)\n }\n\n return result\n } catch (error: unknown) {\n await killTransaction(args.req)\n throw error\n }\n}\n"],"names":["url","buildAfterOperation","buildBeforeOperation","Forbidden","commitTransaction","initTransaction","killTransaction","getFieldsToSign","jwtSign","removeExpiredSessions","refreshOperation","incomingArgs","args","shouldCommit","req","collection","config","operation","collectionConfig","payload","secret","user","t","parsedURL","parse","isGraphQL","pathname","routes","graphQL","db","findOne","slug","where","id","equals","sid","_sid","auth","useSessions","disableLocalStrategy","Array","isArray","sessions","existingSession","find","now","Date","tokenExpInMs","tokenExpiration","expiresAt","getTime","updatedAt","updateOne","data","returning","findByID","depth","_strategy","result","refreshHook","hooks","refresh","hookResult","fieldsToSign","email","exp","token","refreshedToken","setCookie","strategy","afterRefresh","length","hook","context","error"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkFileRestrictions.d.ts","sourceRoot":"","sources":["../../src/uploads/checkFileRestrictions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,2BAA2B,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"checkFileRestrictions.d.ts","sourceRoot":"","sources":["../../src/uploads/checkFileRestrictions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,2BAA2B,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAO5E;;GAEG;AACH,eAAO,MAAM,6BAA6B,EAAE,aAgC3C,CAAA;AAED,eAAO,MAAM,qBAAqB,+BAI/B,2BAA2B,KAAG,OAAO,CAAC,IAAI,CA0F5C,CAAA"}
|
|
@@ -3,8 +3,6 @@ import { ValidationError } from '../errors/index.js';
|
|
|
3
3
|
import { validateMimeType } from '../utilities/validateMimeType.js';
|
|
4
4
|
import { validatePDF } from '../utilities/validatePDF.js';
|
|
5
5
|
import { detectSvgFromXml } from './detectSvgFromXml.js';
|
|
6
|
-
import { getFileTypeFallback } from './getFileTypeFallback.js';
|
|
7
|
-
import { validateSvg } from './validateSvg.js';
|
|
8
6
|
/**
|
|
9
7
|
* Restricted file types and their extensions.
|
|
10
8
|
*/ export const RESTRICTED_FILE_EXT_AND_TYPES = [
|
|
@@ -254,30 +252,8 @@ export const checkFileRestrictions = async ({ collection, file, req })=>{
|
|
|
254
252
|
};
|
|
255
253
|
}
|
|
256
254
|
}
|
|
257
|
-
if (!detected && !useTempFiles) {
|
|
258
|
-
|
|
259
|
-
const extIsValid = validateMimeType(mimeTypeFromExtension, configMimeTypes);
|
|
260
|
-
if (!extIsValid) {
|
|
261
|
-
errors.push(`File type ${mimeTypeFromExtension} (from extension ${typeFromExtension}) is not allowed.`);
|
|
262
|
-
} else {
|
|
263
|
-
// SVG security check (text-based files not detectable by buffer)
|
|
264
|
-
if (typeFromExtension.toLowerCase() === 'svg') {
|
|
265
|
-
const isSafeSvg = validateSvg(file.data);
|
|
266
|
-
if (!isSafeSvg) {
|
|
267
|
-
errors.push('SVG file contains potentially harmful content.');
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
// PDF validation
|
|
271
|
-
if (mimeTypeFromExtension === 'application/pdf') {
|
|
272
|
-
const isValidPDF = validatePDF(file.data);
|
|
273
|
-
if (!isValidPDF) {
|
|
274
|
-
errors.push('Invalid or corrupted PDF file.');
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
if (expectsDetectableType(mimeTypeFromExtension)) {
|
|
279
|
-
req.payload.logger.warn(`File buffer returned no detectable MIME type for ${file.name}. Falling back to extension-based validation.`);
|
|
280
|
-
}
|
|
255
|
+
if (!detected && expectsDetectableType(typeFromExtension) && !useTempFiles) {
|
|
256
|
+
errors.push(`File buffer returned no detectable MIME type.`);
|
|
281
257
|
}
|
|
282
258
|
const passesMimeTypeCheck = detected?.mime && validateMimeType(detected.mime, configMimeTypes);
|
|
283
259
|
if (passesMimeTypeCheck && detected?.mime === 'application/pdf') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/uploads/checkFileRestrictions.ts"],"sourcesContent":["import { fileTypeFromBuffer } from 'file-type'\n\nimport type { checkFileRestrictionsParams, FileAllowList } from './types.js'\n\nimport { ValidationError } from '../errors/index.js'\nimport { validateMimeType } from '../utilities/validateMimeType.js'\nimport { validatePDF } from '../utilities/validatePDF.js'\nimport { detectSvgFromXml } from './detectSvgFromXml.js'\nimport { getFileTypeFallback } from './getFileTypeFallback.js'\nimport { validateSvg } from './validateSvg.js'\n\n/**\n * Restricted file types and their extensions.\n */\nexport const RESTRICTED_FILE_EXT_AND_TYPES: FileAllowList = [\n { extensions: ['exe', 'dll'], mimeType: 'application/x-msdownload' },\n { extensions: ['exe', 'com', 'app', 'action'], mimeType: 'application/x-executable' },\n { extensions: ['bat', 'cmd'], mimeType: 'application/x-msdos-program' },\n { extensions: ['exe', 'com'], mimeType: 'application/x-ms-dos-executable' },\n { extensions: ['dmg'], mimeType: 'application/x-apple-diskimage' },\n { extensions: ['deb'], mimeType: 'application/x-debian-package' },\n { extensions: ['rpm'], mimeType: 'application/x-redhat-package-manager' },\n { extensions: ['exe', 'dll'], mimeType: 'application/vnd.microsoft.portable-executable' },\n { extensions: ['msi'], mimeType: 'application/x-msi' },\n { extensions: ['jar', 'ear', 'war'], mimeType: 'application/java-archive' },\n { extensions: ['desktop'], mimeType: 'application/x-desktop' },\n { extensions: ['cpl'], mimeType: 'application/x-cpl' },\n { extensions: ['lnk'], mimeType: 'application/x-ms-shortcut' },\n { extensions: ['pkg'], mimeType: 'application/x-apple-installer' },\n { extensions: ['htm', 'html', 'shtml', 'xhtml'], mimeType: 'text/html' },\n { extensions: ['php', 'phtml'], mimeType: 'application/x-httpd-php' },\n { extensions: ['js', 'jse'], mimeType: 'text/javascript' },\n { extensions: ['jsp'], mimeType: 'application/x-jsp' },\n { extensions: ['py'], mimeType: 'text/x-python' },\n { extensions: ['rb'], mimeType: 'text/x-ruby' },\n { extensions: ['pl'], mimeType: 'text/x-perl' },\n { extensions: ['ps1', 'psc1', 'psd1', 'psh', 'psm1'], mimeType: 'application/x-powershell' },\n { extensions: ['vbe', 'vbs'], mimeType: 'application/x-vbscript' },\n { extensions: ['ws', 'wsc', 'wsf', 'wsh'], mimeType: 'application/x-ms-wsh' },\n { extensions: ['scr'], mimeType: 'application/x-msdownload' },\n { extensions: ['asp', 'aspx'], mimeType: 'application/x-asp' },\n { extensions: ['hta'], mimeType: 'application/x-hta' },\n { extensions: ['reg'], mimeType: 'application/x-registry' },\n { extensions: ['url'], mimeType: 'application/x-url' },\n { extensions: ['workflow'], mimeType: 'application/x-workflow' },\n { extensions: ['command'], mimeType: 'application/x-command' },\n]\n\nexport const checkFileRestrictions = async ({\n collection,\n file,\n req,\n}: checkFileRestrictionsParams): Promise<void> => {\n const errors: string[] = []\n const { upload: uploadConfig } = collection\n const useTempFiles = req?.payload?.config?.upload?.useTempFiles ?? false\n const configMimeTypes =\n uploadConfig &&\n typeof uploadConfig === 'object' &&\n 'mimeTypes' in uploadConfig &&\n Array.isArray(uploadConfig.mimeTypes)\n ? uploadConfig.mimeTypes\n : []\n\n const allowRestrictedFileTypes =\n uploadConfig && typeof uploadConfig === 'object' && 'allowRestrictedFileTypes' in uploadConfig\n ? (uploadConfig as { allowRestrictedFileTypes?: boolean }).allowRestrictedFileTypes\n : false\n\n const expectsDetectableType = (mimeType: string): boolean => {\n const textBasedTypes = ['/svg', 'image/svg+xml', 'image/x-xbitmap', 'image/x-xpixmap']\n\n if (textBasedTypes.includes(mimeType)) {\n return false\n }\n\n return (\n mimeType.startsWith('image/') ||\n mimeType.startsWith('video/') ||\n mimeType.startsWith('audio/') ||\n mimeType === 'application/pdf'\n )\n }\n\n // Skip validation if `allowRestrictedFileTypes` is true\n if (allowRestrictedFileTypes) {\n return\n }\n\n // Secondary mimetype check to assess file type from buffer\n if (configMimeTypes.length > 0) {\n let detected = await fileTypeFromBuffer(file.data)\n const typeFromExtension = file.name.split('.').pop() || ''\n\n // Handle SVG files that are detected as XML due to <?xml declarations\n if (\n detected?.mime === 'application/xml' &&\n configMimeTypes.some(\n (type) => type.includes('image/') && (type.includes('svg') || type === 'image/*'),\n )\n ) {\n const isSvg = detectSvgFromXml(file.data)\n if (isSvg) {\n detected = { ext: 'svg' as any, mime: 'image/svg+xml' as any }\n }\n }\n\n if (!detected && !useTempFiles) {\n const mimeTypeFromExtension = getFileTypeFallback(file.name).mime\n const extIsValid = validateMimeType(mimeTypeFromExtension, configMimeTypes)\n\n if (!extIsValid) {\n errors.push(\n `File type ${mimeTypeFromExtension} (from extension ${typeFromExtension}) is not allowed.`,\n )\n } else {\n // SVG security check (text-based files not detectable by buffer)\n if (typeFromExtension.toLowerCase() === 'svg') {\n const isSafeSvg = validateSvg(file.data)\n if (!isSafeSvg) {\n errors.push('SVG file contains potentially harmful content.')\n }\n }\n\n // PDF validation\n if (mimeTypeFromExtension === 'application/pdf') {\n const isValidPDF = validatePDF(file.data)\n if (!isValidPDF) {\n errors.push('Invalid or corrupted PDF file.')\n }\n }\n }\n\n if (expectsDetectableType(mimeTypeFromExtension)) {\n req.payload.logger.warn(\n `File buffer returned no detectable MIME type for ${file.name}. Falling back to extension-based validation.`,\n )\n }\n }\n\n const passesMimeTypeCheck = detected?.mime && validateMimeType(detected.mime, configMimeTypes)\n\n if (passesMimeTypeCheck && detected?.mime === 'application/pdf') {\n const isValidPDF = validatePDF(file?.data)\n if (!isValidPDF) {\n errors.push('Invalid PDF file.')\n }\n }\n\n if (detected && !passesMimeTypeCheck) {\n errors.push(`Invalid MIME type: ${detected.mime}.`)\n }\n } else {\n const isRestricted = RESTRICTED_FILE_EXT_AND_TYPES.some((type) => {\n const hasRestrictedExt = type.extensions.some((ext) => file.name.toLowerCase().endsWith(ext))\n const hasRestrictedMime = type.mimeType === file.mimetype\n return hasRestrictedExt || hasRestrictedMime\n })\n if (isRestricted) {\n errors.push(\n `File type '${file.mimetype}' not allowed ${file.name}: Restricted file type detected -- set 'allowRestrictedFileTypes' to true to skip this check for this Collection.`,\n )\n }\n }\n\n if (errors.length > 0) {\n req.payload.logger.error(errors.join(', '))\n throw new ValidationError({\n errors: [{ message: errors.join(', '), path: 'file' }],\n })\n }\n}\n"],"names":["fileTypeFromBuffer","ValidationError","validateMimeType","validatePDF","detectSvgFromXml","getFileTypeFallback","validateSvg","RESTRICTED_FILE_EXT_AND_TYPES","extensions","mimeType","checkFileRestrictions","collection","file","req","errors","upload","uploadConfig","useTempFiles","payload","config","configMimeTypes","Array","isArray","mimeTypes","allowRestrictedFileTypes","expectsDetectableType","textBasedTypes","includes","startsWith","length","detected","data","typeFromExtension","name","split","pop","mime","some","type","isSvg","ext","mimeTypeFromExtension","extIsValid","push","toLowerCase","isSafeSvg","isValidPDF","logger","warn","passesMimeTypeCheck","isRestricted","hasRestrictedExt","endsWith","hasRestrictedMime","mimetype","error","join","message","path"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/uploads/checkFileRestrictions.ts"],"sourcesContent":["import { fileTypeFromBuffer } from 'file-type'\n\nimport type { checkFileRestrictionsParams, FileAllowList } from './types.js'\n\nimport { ValidationError } from '../errors/index.js'\nimport { validateMimeType } from '../utilities/validateMimeType.js'\nimport { validatePDF } from '../utilities/validatePDF.js'\nimport { detectSvgFromXml } from './detectSvgFromXml.js'\n\n/**\n * Restricted file types and their extensions.\n */\nexport const RESTRICTED_FILE_EXT_AND_TYPES: FileAllowList = [\n { extensions: ['exe', 'dll'], mimeType: 'application/x-msdownload' },\n { extensions: ['exe', 'com', 'app', 'action'], mimeType: 'application/x-executable' },\n { extensions: ['bat', 'cmd'], mimeType: 'application/x-msdos-program' },\n { extensions: ['exe', 'com'], mimeType: 'application/x-ms-dos-executable' },\n { extensions: ['dmg'], mimeType: 'application/x-apple-diskimage' },\n { extensions: ['deb'], mimeType: 'application/x-debian-package' },\n { extensions: ['rpm'], mimeType: 'application/x-redhat-package-manager' },\n { extensions: ['exe', 'dll'], mimeType: 'application/vnd.microsoft.portable-executable' },\n { extensions: ['msi'], mimeType: 'application/x-msi' },\n { extensions: ['jar', 'ear', 'war'], mimeType: 'application/java-archive' },\n { extensions: ['desktop'], mimeType: 'application/x-desktop' },\n { extensions: ['cpl'], mimeType: 'application/x-cpl' },\n { extensions: ['lnk'], mimeType: 'application/x-ms-shortcut' },\n { extensions: ['pkg'], mimeType: 'application/x-apple-installer' },\n { extensions: ['htm', 'html', 'shtml', 'xhtml'], mimeType: 'text/html' },\n { extensions: ['php', 'phtml'], mimeType: 'application/x-httpd-php' },\n { extensions: ['js', 'jse'], mimeType: 'text/javascript' },\n { extensions: ['jsp'], mimeType: 'application/x-jsp' },\n { extensions: ['py'], mimeType: 'text/x-python' },\n { extensions: ['rb'], mimeType: 'text/x-ruby' },\n { extensions: ['pl'], mimeType: 'text/x-perl' },\n { extensions: ['ps1', 'psc1', 'psd1', 'psh', 'psm1'], mimeType: 'application/x-powershell' },\n { extensions: ['vbe', 'vbs'], mimeType: 'application/x-vbscript' },\n { extensions: ['ws', 'wsc', 'wsf', 'wsh'], mimeType: 'application/x-ms-wsh' },\n { extensions: ['scr'], mimeType: 'application/x-msdownload' },\n { extensions: ['asp', 'aspx'], mimeType: 'application/x-asp' },\n { extensions: ['hta'], mimeType: 'application/x-hta' },\n { extensions: ['reg'], mimeType: 'application/x-registry' },\n { extensions: ['url'], mimeType: 'application/x-url' },\n { extensions: ['workflow'], mimeType: 'application/x-workflow' },\n { extensions: ['command'], mimeType: 'application/x-command' },\n]\n\nexport const checkFileRestrictions = async ({\n collection,\n file,\n req,\n}: checkFileRestrictionsParams): Promise<void> => {\n const errors: string[] = []\n const { upload: uploadConfig } = collection\n const useTempFiles = req?.payload?.config?.upload?.useTempFiles ?? false\n const configMimeTypes =\n uploadConfig &&\n typeof uploadConfig === 'object' &&\n 'mimeTypes' in uploadConfig &&\n Array.isArray(uploadConfig.mimeTypes)\n ? uploadConfig.mimeTypes\n : []\n\n const allowRestrictedFileTypes =\n uploadConfig && typeof uploadConfig === 'object' && 'allowRestrictedFileTypes' in uploadConfig\n ? (uploadConfig as { allowRestrictedFileTypes?: boolean }).allowRestrictedFileTypes\n : false\n\n const expectsDetectableType = (mimeType: string): boolean => {\n const textBasedTypes = ['/svg', 'image/svg+xml', 'image/x-xbitmap', 'image/x-xpixmap']\n\n if (textBasedTypes.includes(mimeType)) {\n return false\n }\n\n return (\n mimeType.startsWith('image/') ||\n mimeType.startsWith('video/') ||\n mimeType.startsWith('audio/') ||\n mimeType === 'application/pdf'\n )\n }\n\n // Skip validation if `allowRestrictedFileTypes` is true\n if (allowRestrictedFileTypes) {\n return\n }\n\n // Secondary mimetype check to assess file type from buffer\n if (configMimeTypes.length > 0) {\n let detected = await fileTypeFromBuffer(file.data)\n const typeFromExtension = file.name.split('.').pop() || ''\n\n // Handle SVG files that are detected as XML due to <?xml declarations\n if (\n detected?.mime === 'application/xml' &&\n configMimeTypes.some(\n (type) => type.includes('image/') && (type.includes('svg') || type === 'image/*'),\n )\n ) {\n const isSvg = detectSvgFromXml(file.data)\n if (isSvg) {\n detected = { ext: 'svg' as any, mime: 'image/svg+xml' as any }\n }\n }\n\n if (!detected && expectsDetectableType(typeFromExtension) && !useTempFiles) {\n errors.push(`File buffer returned no detectable MIME type.`)\n }\n\n const passesMimeTypeCheck = detected?.mime && validateMimeType(detected.mime, configMimeTypes)\n\n if (passesMimeTypeCheck && detected?.mime === 'application/pdf') {\n const isValidPDF = validatePDF(file?.data)\n if (!isValidPDF) {\n errors.push('Invalid PDF file.')\n }\n }\n\n if (detected && !passesMimeTypeCheck) {\n errors.push(`Invalid MIME type: ${detected.mime}.`)\n }\n } else {\n const isRestricted = RESTRICTED_FILE_EXT_AND_TYPES.some((type) => {\n const hasRestrictedExt = type.extensions.some((ext) => file.name.toLowerCase().endsWith(ext))\n const hasRestrictedMime = type.mimeType === file.mimetype\n return hasRestrictedExt || hasRestrictedMime\n })\n if (isRestricted) {\n errors.push(\n `File type '${file.mimetype}' not allowed ${file.name}: Restricted file type detected -- set 'allowRestrictedFileTypes' to true to skip this check for this Collection.`,\n )\n }\n }\n\n if (errors.length > 0) {\n req.payload.logger.error(errors.join(', '))\n throw new ValidationError({\n errors: [{ message: errors.join(', '), path: 'file' }],\n })\n }\n}\n"],"names":["fileTypeFromBuffer","ValidationError","validateMimeType","validatePDF","detectSvgFromXml","RESTRICTED_FILE_EXT_AND_TYPES","extensions","mimeType","checkFileRestrictions","collection","file","req","errors","upload","uploadConfig","useTempFiles","payload","config","configMimeTypes","Array","isArray","mimeTypes","allowRestrictedFileTypes","expectsDetectableType","textBasedTypes","includes","startsWith","length","detected","data","typeFromExtension","name","split","pop","mime","some","type","isSvg","ext","push","passesMimeTypeCheck","isValidPDF","isRestricted","hasRestrictedExt","toLowerCase","endsWith","hasRestrictedMime","mimetype","logger","error","join","message","path"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateMimeType.d.ts","sourceRoot":"","sources":["../../src/utilities/validateMimeType.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,aAAc,MAAM,oBAAoB,MAAM,EAAE,KAAG,
|
|
1
|
+
{"version":3,"file":"validateMimeType.d.ts","sourceRoot":"","sources":["../../src/utilities/validateMimeType.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,aAAc,MAAM,oBAAoB,MAAM,EAAE,KAAG,OAG/E,CAAA"}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
export const validateMimeType = (mimeType, allowedMimeTypes)=>{
|
|
2
|
-
if (allowedMimeTypes.length === 0) {
|
|
3
|
-
return true;
|
|
4
|
-
}
|
|
5
2
|
const cleanedMimeTypes = allowedMimeTypes.map((v)=>v.replace('*', ''));
|
|
6
3
|
return cleanedMimeTypes.some((cleanedMimeType)=>mimeType.startsWith(cleanedMimeType));
|
|
7
4
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/validateMimeType.ts"],"sourcesContent":["export const validateMimeType = (mimeType: string, allowedMimeTypes: string[]): boolean => {\n
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/validateMimeType.ts"],"sourcesContent":["export const validateMimeType = (mimeType: string, allowedMimeTypes: string[]): boolean => {\n const cleanedMimeTypes = allowedMimeTypes.map((v) => v.replace('*', ''))\n return cleanedMimeTypes.some((cleanedMimeType) => mimeType.startsWith(cleanedMimeType))\n}\n"],"names":["validateMimeType","mimeType","allowedMimeTypes","cleanedMimeTypes","map","v","replace","some","cleanedMimeType","startsWith"],"mappings":"AAAA,OAAO,MAAMA,mBAAmB,CAACC,UAAkBC;IACjD,MAAMC,mBAAmBD,iBAAiBE,GAAG,CAAC,CAACC,IAAMA,EAAEC,OAAO,CAAC,KAAK;IACpE,OAAOH,iBAAiBI,IAAI,CAAC,CAACC,kBAAoBP,SAASQ,UAAU,CAACD;AACxE,EAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payload",
|
|
3
|
-
"version": "3.69.0-
|
|
3
|
+
"version": "3.69.0-internal.35bf893",
|
|
4
4
|
"description": "Node, React, Headless CMS and Application Framework built on Next.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"admin panel",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
"undici": "7.10.0",
|
|
108
108
|
"uuid": "10.0.0",
|
|
109
109
|
"ws": "^8.16.0",
|
|
110
|
-
"@payloadcms/translations": "3.69.0-
|
|
110
|
+
"@payloadcms/translations": "3.69.0-internal.35bf893"
|
|
111
111
|
},
|
|
112
112
|
"devDependencies": {
|
|
113
113
|
"@hyrious/esbuild-plugin-commonjs": "0.2.6",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validateSvg.d.ts","sourceRoot":"","sources":["../../src/uploads/validateSvg.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAqDnD"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Validate SVG content for security vulnerabilities
|
|
3
|
-
* Detects and blocks malicious patterns commonly used in SVG-based attacks
|
|
4
|
-
*/ export function validateSvg(buffer) {
|
|
5
|
-
try {
|
|
6
|
-
const content = buffer.toString('utf8');
|
|
7
|
-
const dangerousPatterns = [
|
|
8
|
-
// Script tags
|
|
9
|
-
/<script[\s>]/i,
|
|
10
|
-
/<\/script>/i,
|
|
11
|
-
// Event handlers (onclick, onload, onerror, etc.)
|
|
12
|
-
/\son\w+\s*=/i,
|
|
13
|
-
// JavaScript URLs
|
|
14
|
-
/javascript:/i,
|
|
15
|
-
/data:text\/html/i,
|
|
16
|
-
// Foreign objects (can embed HTML)
|
|
17
|
-
/<foreignObject[\s>]/i,
|
|
18
|
-
// Embedded iframes
|
|
19
|
-
/<iframe[\s>]/i,
|
|
20
|
-
// Embedded objects and embeds
|
|
21
|
-
/<object[\s>]/i,
|
|
22
|
-
/<embed[\s>]/i,
|
|
23
|
-
// Base64 encoded scripts (common obfuscation technique)
|
|
24
|
-
/data:image\/svg\+xml;base64,[\w+/]*PHNjcmlwdA/i,
|
|
25
|
-
// XLink href with javascript (deprecated but still dangerous)
|
|
26
|
-
/xlink:href\s*=\s*["']javascript:/i,
|
|
27
|
-
// Import statements
|
|
28
|
-
/@import/i,
|
|
29
|
-
// External resource references that could be dangerous
|
|
30
|
-
/<!ENTITY/i,
|
|
31
|
-
/<!DOCTYPE[^>]*\[/i,
|
|
32
|
-
// Attempt to use CDATA to hide scripts
|
|
33
|
-
/<!\[CDATA\[[\s\S]*<script/i
|
|
34
|
-
];
|
|
35
|
-
for (const pattern of dangerousPatterns){
|
|
36
|
-
if (pattern.test(content)) {
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return true;
|
|
41
|
-
} catch (_error) {
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
//# sourceMappingURL=validateSvg.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/uploads/validateSvg.ts"],"sourcesContent":["/**\n * Validate SVG content for security vulnerabilities\n * Detects and blocks malicious patterns commonly used in SVG-based attacks\n */\nexport function validateSvg(buffer: Buffer): boolean {\n try {\n const content = buffer.toString('utf8')\n\n const dangerousPatterns = [\n // Script tags\n /<script[\\s>]/i,\n /<\\/script>/i,\n\n // Event handlers (onclick, onload, onerror, etc.)\n /\\son\\w+\\s*=/i,\n\n // JavaScript URLs\n /javascript:/i,\n /data:text\\/html/i,\n\n // Foreign objects (can embed HTML)\n /<foreignObject[\\s>]/i,\n\n // Embedded iframes\n /<iframe[\\s>]/i,\n\n // Embedded objects and embeds\n /<object[\\s>]/i,\n /<embed[\\s>]/i,\n\n // Base64 encoded scripts (common obfuscation technique)\n /data:image\\/svg\\+xml;base64,[\\w+/]*PHNjcmlwdA/i, // <script in base64\n\n // XLink href with javascript (deprecated but still dangerous)\n /xlink:href\\s*=\\s*[\"']javascript:/i,\n\n // Import statements\n /@import/i,\n\n // External resource references that could be dangerous\n /<!ENTITY/i,\n /<!DOCTYPE[^>]*\\[/i, // DOCTYPE with internal subset\n\n // Attempt to use CDATA to hide scripts\n /<!\\[CDATA\\[[\\s\\S]*<script/i,\n ]\n\n for (const pattern of dangerousPatterns) {\n if (pattern.test(content)) {\n return false\n }\n }\n\n return true\n } catch (_error) {\n return false\n }\n}\n"],"names":["validateSvg","buffer","content","toString","dangerousPatterns","pattern","test","_error"],"mappings":"AAAA;;;CAGC,GACD,OAAO,SAASA,YAAYC,MAAc;IACxC,IAAI;QACF,MAAMC,UAAUD,OAAOE,QAAQ,CAAC;QAEhC,MAAMC,oBAAoB;YACxB,cAAc;YACd;YACA;YAEA,kDAAkD;YAClD;YAEA,kBAAkB;YAClB;YACA;YAEA,mCAAmC;YACnC;YAEA,mBAAmB;YACnB;YAEA,8BAA8B;YAC9B;YACA;YAEA,wDAAwD;YACxD;YAEA,8DAA8D;YAC9D;YAEA,oBAAoB;YACpB;YAEA,uDAAuD;YACvD;YACA;YAEA,uCAAuC;YACvC;SACD;QAED,KAAK,MAAMC,WAAWD,kBAAmB;YACvC,IAAIC,QAAQC,IAAI,CAACJ,UAAU;gBACzB,OAAO;YACT;QACF;QAEA,OAAO;IACT,EAAE,OAAOK,QAAQ;QACf,OAAO;IACT;AACF"}
|