From 09008bf0f1a535db7c57ea015b64fabd6f0eae7d Mon Sep 17 00:00:00 2001 From: Marc Derhammer Date: Tue, 19 Sep 2023 13:17:07 -0400 Subject: [PATCH 1/5] fix: use last index of period to determine extension related to #8753 --- spec/ParseFile.spec.js | 24 ++++++++++++++++++++++++ src/Routers/FilesRouter.js | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js index f083c90ae4..e04e45fd75 100644 --- a/spec/ParseFile.spec.js +++ b/spec/ParseFile.spec.js @@ -1364,6 +1364,30 @@ describe('Parse.File testing', () => { ); }); + it('works with a period in the file name', async () => { + await reconfigureServer({ + fileUpload: { + enableForPublic: true, + }, + }); + const headers = { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }; + await expectAsync( + request({ + method: 'POST', + headers: headers, + url: 'http://localhost:8378/1/files/file.png.html', + body: '\n', + }).catch(e => { + throw new Error(e.data.error); + }) + ).toBeRejectedWith( + new Parse.Error(Parse.Error.FILE_SAVE_ERROR, `File upload of extension html is disabled.`) + ); + }); + it('works with array', async () => { await reconfigureServer({ fileUpload: { diff --git a/src/Routers/FilesRouter.js b/src/Routers/FilesRouter.js index cbb59fdcdd..94d6549325 100644 --- a/src/Routers/FilesRouter.js +++ b/src/Routers/FilesRouter.js @@ -155,7 +155,7 @@ export class FilesRouter { }; let extension = contentType; if (filename && filename.includes('.')) { - extension = filename.split('.')[1]; + extension = filename.split('.')[filename.split('.').length - 1]; } else if (contentType && contentType.includes('/')) { extension = contentType.split('/')[1]; } From b2e90ffe8d600107435e127e64cf2aff66722b80 Mon Sep 17 00:00:00 2001 From: Marc Derhammer Date: Tue, 19 Sep 2023 16:30:39 -0400 Subject: [PATCH 2/5] Added some more testing for bad file extensions and also invalid filenames --- spec/ParseFile.spec.js | 66 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js index e04e45fd75..15aab1e281 100644 --- a/spec/ParseFile.spec.js +++ b/spec/ParseFile.spec.js @@ -1374,18 +1374,60 @@ describe('Parse.File testing', () => { 'X-Parse-Application-Id': 'test', 'X-Parse-REST-API-Key': 'rest', }; - await expectAsync( - request({ - method: 'POST', - headers: headers, - url: 'http://localhost:8378/1/files/file.png.html', - body: '\n', - }).catch(e => { - throw new Error(e.data.error); - }) - ).toBeRejectedWith( - new Parse.Error(Parse.Error.FILE_SAVE_ERROR, `File upload of extension html is disabled.`) - ); + + const values = ['file.png.html', 'file.txt.png.html', 'file.png.txt.html']; + + for (const value of values) { + await expectAsync( + request({ + method: 'POST', + headers: headers, + url: `http://localhost:8378/1/files/${value}`, + body: '\n', + }).catch(e => { + throw new Error(e.data.error); + }) + ).toBeRejectedWith( + new Parse.Error(Parse.Error.FILE_SAVE_ERROR, `File upload of extension html is disabled.`) + ); + } + }); + + it('works to stop invalid filenames', async () => { + await reconfigureServer({ + fileUpload: { + enableForPublic: true, + }, + }); + const headers = { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }; + + const values = [ + '!invalid.png', + '.png', + '.html', + ' .html', + '.png.html', + '~invalid.png', + '-invalid.png', + ]; + + for (const value of values) { + await expectAsync( + request({ + method: 'POST', + headers: headers, + url: `http://localhost:8378/1/files/${value}`, + body: '\n', + }).catch(e => { + throw new Error(e.data.error); + }) + ).toBeRejectedWith( + new Parse.Error(Parse.Error.INVALID_FILE_NAME, `Filename contains invalid characters.`) + ); + } }); it('works with array', async () => { From 884512d19bd40db500742ee868cf7536a924f8d4 Mon Sep 17 00:00:00 2001 From: Marc Derhammer Date: Tue, 19 Sep 2023 19:47:47 -0400 Subject: [PATCH 3/5] Change from split to lastIndexOf --- src/Routers/FilesRouter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Routers/FilesRouter.js b/src/Routers/FilesRouter.js index 94d6549325..a063fecb95 100644 --- a/src/Routers/FilesRouter.js +++ b/src/Routers/FilesRouter.js @@ -155,7 +155,7 @@ export class FilesRouter { }; let extension = contentType; if (filename && filename.includes('.')) { - extension = filename.split('.')[filename.split('.').length - 1]; + extension = filename.substring(filename.lastIndexOf('.') + 1); } else if (contentType && contentType.includes('/')) { extension = contentType.split('/')[1]; } From 2cd301f7d5579005d633975a11c8df5686db91cf Mon Sep 17 00:00:00 2001 From: Marc Derhammer Date: Thu, 21 Sep 2023 21:46:26 -0400 Subject: [PATCH 4/5] Update spec/ParseFile.spec.js Co-authored-by: Manuel <5673677+mtrezza@users.noreply.github.com> Signed-off-by: Marc Derhammer --- spec/ParseFile.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js index 15aab1e281..04fb4da9ce 100644 --- a/spec/ParseFile.spec.js +++ b/spec/ParseFile.spec.js @@ -1368,6 +1368,7 @@ describe('Parse.File testing', () => { await reconfigureServer({ fileUpload: { enableForPublic: true, + fileExtensions: ['^[^hH][^tT][^mM][^lL]?$'], }, }); const headers = { From 3f26fdaa7d03563d62ea5b8f612c6da5ad8468ef Mon Sep 17 00:00:00 2001 From: Marc Derhammer Date: Thu, 21 Sep 2023 21:46:37 -0400 Subject: [PATCH 5/5] Update spec/ParseFile.spec.js Co-authored-by: Manuel <5673677+mtrezza@users.noreply.github.com> Signed-off-by: Marc Derhammer --- spec/ParseFile.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js index 04fb4da9ce..d12c9e5d6f 100644 --- a/spec/ParseFile.spec.js +++ b/spec/ParseFile.spec.js @@ -1398,6 +1398,7 @@ describe('Parse.File testing', () => { await reconfigureServer({ fileUpload: { enableForPublic: true, + fileExtensions: ['^[^hH][^tT][^mM][^lL]?$'], }, }); const headers = {