From 2cc2be81c1edb876e79d081a260784ddd291eb0e Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 24 Jul 2023 00:05:45 +1000 Subject: [PATCH 1/6] Update ParseFile.spec.js --- spec/ParseFile.spec.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js index f083c90ae4..09a8081fa3 100644 --- a/spec/ParseFile.spec.js +++ b/spec/ParseFile.spec.js @@ -1315,7 +1315,7 @@ describe('Parse.File testing', () => { }); describe('fileExtensions', () => { - it('works with _ContentType', async () => { + fit('works with _ContentType', async () => { await reconfigureServer({ fileUpload: { enableForPublic: true, @@ -1362,6 +1362,8 @@ describe('Parse.File testing', () => { ).toBeRejectedWith( new Parse.Error(Parse.Error.FILE_SAVE_ERROR, `File upload of extension html is disabled.`) ); + const file = new Parse.File('parse-server-logo.png', { base64: 'ParseA==' }); + await file.save(); }); it('works with array', async () => { From 8b473aed76f0b986e8bc803c4deb3ec2de7852cb Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 24 Jul 2023 00:08:20 +1000 Subject: [PATCH 2/6] Update ParseFile.spec.js --- spec/ParseFile.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js index 09a8081fa3..20532ad0dd 100644 --- a/spec/ParseFile.spec.js +++ b/spec/ParseFile.spec.js @@ -1315,7 +1315,7 @@ describe('Parse.File testing', () => { }); describe('fileExtensions', () => { - fit('works with _ContentType', async () => { + it('works with _ContentType', async () => { await reconfigureServer({ fileUpload: { enableForPublic: true, @@ -1340,7 +1340,7 @@ describe('Parse.File testing', () => { ); }); - it('works without Content-Type', async () => { + fit('works without Content-Type', async () => { await reconfigureServer({ fileUpload: { enableForPublic: true, From d987059e7c08fba56bb6a65092842608d522e35b Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 24 Jul 2023 00:29:56 +1000 Subject: [PATCH 3/6] fix: default fileExtension regex does not allow text-plain --- spec/ParseFile.spec.js | 4 ++-- src/Options/Definitions.js | 4 ++-- src/Options/docs.js | 2 +- src/Options/index.js | 4 ++-- src/Routers/FilesRouter.js | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js index 20532ad0dd..df85136354 100644 --- a/spec/ParseFile.spec.js +++ b/spec/ParseFile.spec.js @@ -1340,7 +1340,7 @@ describe('Parse.File testing', () => { ); }); - fit('works without Content-Type', async () => { + it('works without Content-Type', async () => { await reconfigureServer({ fileUpload: { enableForPublic: true, @@ -1362,7 +1362,7 @@ describe('Parse.File testing', () => { ).toBeRejectedWith( new Parse.Error(Parse.Error.FILE_SAVE_ERROR, `File upload of extension html is disabled.`) ); - const file = new Parse.File('parse-server-logo.png', { base64: 'ParseA==' }); + const file = new Parse.File('parse-server-logo', { base64: 'ParseA==' }); await file.save(); }); diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index 7a1e56bad0..61794057d4 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -1001,9 +1001,9 @@ module.exports.FileUploadOptions = { fileExtensions: { env: 'PARSE_SERVER_FILE_UPLOAD_FILE_EXTENSIONS', help: - "Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^[^hH][^tT][^mM][^lL]?$` which allows any file extension except HTML files.", + "Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!html$|htm$).*` which allows any file extension except HTML files.", action: parsers.arrayParser, - default: ['^[^hH][^tT][^mM][^lL]?$'], + default: ['^(?!html$|htm$).*'], }, }; module.exports.DatabaseOptions = { diff --git a/src/Options/docs.js b/src/Options/docs.js index 09e6f5b3b4..0dfb1a9ef3 100644 --- a/src/Options/docs.js +++ b/src/Options/docs.js @@ -226,7 +226,7 @@ * @property {Boolean} enableForAnonymousUser Is true if file upload should be allowed for anonymous users. * @property {Boolean} enableForAuthenticatedUser Is true if file upload should be allowed for authenticated users. * @property {Boolean} enableForPublic Is true if file upload should be allowed for anyone, regardless of user authentication. - * @property {String[]} fileExtensions Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^[^hH][^tT][^mM][^lL]?$` which allows any file extension except HTML files. + * @property {String[]} fileExtensions Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!html$|htm$).*` which allows any file extension except HTML files. */ /** diff --git a/src/Options/index.js b/src/Options/index.js index d501b996dd..8d4b0f89cf 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -567,8 +567,8 @@ export interface PasswordPolicyOptions { } export interface FileUploadOptions { - /* Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^[^hH][^tT][^mM][^lL]?$` which allows any file extension except HTML files. - :DEFAULT: ["^[^hH][^tT][^mM][^lL]?$"] */ + /* Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!html$|htm$).*` which allows any file extension except HTML files. + :DEFAULT: ["^(?!html$|htm$).*"] */ fileExtensions: ?(string[]); /* Is true if file upload should be allowed for anonymous users. :DEFAULT: false */ diff --git a/src/Routers/FilesRouter.js b/src/Routers/FilesRouter.js index cbb59fdcdd..e803ede9da 100644 --- a/src/Routers/FilesRouter.js +++ b/src/Routers/FilesRouter.js @@ -148,7 +148,7 @@ export class FilesRouter { return true; } const regex = new RegExp(ext); - if (regex.test(extension)) { + if (regex.test(extension?.toLowerCase())) { return true; } }); From 5da8d16c4b10a3c4cf9a522959a6031930155621 Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 24 Jul 2023 14:20:29 +1000 Subject: [PATCH 4/6] wip --- src/Options/index.js | 4 ++-- src/Routers/FilesRouter.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Options/index.js b/src/Options/index.js index 8d4b0f89cf..575d66b519 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -567,8 +567,8 @@ export interface PasswordPolicyOptions { } export interface FileUploadOptions { - /* Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!html$|htm$).*` which allows any file extension except HTML files. - :DEFAULT: ["^(?!html$|htm$).*"] */ + /* Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!html?$)` which allows any file extension except HTML files. + :DEFAULT: ["^(?!html?$)"] */ fileExtensions: ?(string[]); /* Is true if file upload should be allowed for anonymous users. :DEFAULT: false */ diff --git a/src/Routers/FilesRouter.js b/src/Routers/FilesRouter.js index e803ede9da..cbb59fdcdd 100644 --- a/src/Routers/FilesRouter.js +++ b/src/Routers/FilesRouter.js @@ -148,7 +148,7 @@ export class FilesRouter { return true; } const regex = new RegExp(ext); - if (regex.test(extension?.toLowerCase())) { + if (regex.test(extension)) { return true; } }); From e0bf9af7c9085c4ab9818f2bf85ea1bdaf7fe3c3 Mon Sep 17 00:00:00 2001 From: dblythy Date: Fri, 28 Jul 2023 02:05:02 +1000 Subject: [PATCH 5/6] add tests --- spec/ParseFile.spec.js | 14 ++++++++++++-- src/Options/Definitions.js | 4 ++-- src/Options/docs.js | 2 +- src/Options/index.js | 2 +- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js index df85136354..5d8d7550ea 100644 --- a/spec/ParseFile.spec.js +++ b/spec/ParseFile.spec.js @@ -1362,8 +1362,18 @@ describe('Parse.File testing', () => { ).toBeRejectedWith( new Parse.Error(Parse.Error.FILE_SAVE_ERROR, `File upload of extension html is disabled.`) ); - const file = new Parse.File('parse-server-logo', { base64: 'ParseA==' }); - await file.save(); + }); + + it('default should allow common types', async () => { + await reconfigureServer({ + fileUpload: { + enableForPublic: true, + }, + }); + for (const type of ['plain', 'txt', 'png', 'jpg', 'gif', 'doc']) { + const file = new Parse.File(`parse-server-logo.${type}`, { base64: 'ParseA==' }); + await file.save(); + } }); it('works with array', async () => { diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index 61794057d4..1d5b360e21 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -1001,9 +1001,9 @@ module.exports.FileUploadOptions = { fileExtensions: { env: 'PARSE_SERVER_FILE_UPLOAD_FILE_EXTENSIONS', help: - "Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!html$|htm$).*` which allows any file extension except HTML files.", + "Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!html?$)` which allows any file extension except HTML files.", action: parsers.arrayParser, - default: ['^(?!html$|htm$).*'], + default: ['^(?!(h|H)(t|T)(m|M)(l|L)?$)'], }, }; module.exports.DatabaseOptions = { diff --git a/src/Options/docs.js b/src/Options/docs.js index 0dfb1a9ef3..e971cdc401 100644 --- a/src/Options/docs.js +++ b/src/Options/docs.js @@ -226,7 +226,7 @@ * @property {Boolean} enableForAnonymousUser Is true if file upload should be allowed for anonymous users. * @property {Boolean} enableForAuthenticatedUser Is true if file upload should be allowed for authenticated users. * @property {Boolean} enableForPublic Is true if file upload should be allowed for anyone, regardless of user authentication. - * @property {String[]} fileExtensions Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!html$|htm$).*` which allows any file extension except HTML files. + * @property {String[]} fileExtensions Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!html?$)` which allows any file extension except HTML files. */ /** diff --git a/src/Options/index.js b/src/Options/index.js index 575d66b519..6de817fc4f 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -568,7 +568,7 @@ export interface PasswordPolicyOptions { export interface FileUploadOptions { /* Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!html?$)` which allows any file extension except HTML files. - :DEFAULT: ["^(?!html?$)"] */ + :DEFAULT: ["^(?!(h|H)(t|T)(m|M)(l|L)?$)"] */ fileExtensions: ?(string[]); /* Is true if file upload should be allowed for anonymous users. :DEFAULT: false */ From ebb1b9cf5278142fa074aab0e60d583299fa6f7b Mon Sep 17 00:00:00 2001 From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com> Date: Sun, 10 Mar 2024 15:01:35 +0100 Subject: [PATCH 6/6] fix definitions --- src/Options/Definitions.js | 2 +- src/Options/docs.js | 2 +- src/Options/index.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index 5ed80f4600..ee1137b7ea 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -1022,7 +1022,7 @@ module.exports.FileUploadOptions = { fileExtensions: { env: 'PARSE_SERVER_FILE_UPLOAD_FILE_EXTENSIONS', help: - "Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!html?$)` which allows any file extension except HTML files.", + "Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!(h|H)(t|T)(m|M)(l|L)?$)` which allows any file extension except HTML files.", action: parsers.arrayParser, default: ['^(?!(h|H)(t|T)(m|M)(l|L)?$)'], }, diff --git a/src/Options/docs.js b/src/Options/docs.js index 3a5763c022..219fc2e5a9 100644 --- a/src/Options/docs.js +++ b/src/Options/docs.js @@ -229,7 +229,7 @@ * @property {Boolean} enableForAnonymousUser Is true if file upload should be allowed for anonymous users. * @property {Boolean} enableForAuthenticatedUser Is true if file upload should be allowed for authenticated users. * @property {Boolean} enableForPublic Is true if file upload should be allowed for anyone, regardless of user authentication. - * @property {String[]} fileExtensions Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!html?$)` which allows any file extension except HTML files. + * @property {String[]} fileExtensions Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!(h|H)(t|T)(m|M)(l|L)?$)` which allows any file extension except HTML files. */ /** diff --git a/src/Options/index.js b/src/Options/index.js index 6a3c494066..067ac15ff3 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -576,7 +576,7 @@ export interface PasswordPolicyOptions { } export interface FileUploadOptions { - /* Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!html?$)` which allows any file extension except HTML files. + /* Sets the allowed file extensions for uploading files. The extension is defined as an array of file extensions, or a regex pattern.

It is recommended to restrict the file upload extensions as much as possible. HTML files are especially problematic as they may be used by an attacker who uploads a HTML form to look legitimate under your app's domain name, or to compromise the session token of another user via accessing the browser's local storage.

Defaults to `^(?!(h|H)(t|T)(m|M)(l|L)?$)` which allows any file extension except HTML files. :DEFAULT: ["^(?!(h|H)(t|T)(m|M)(l|L)?$)"] */ fileExtensions: ?(string[]); /* Is true if file upload should be allowed for anonymous users.