From 4c9e95674ad081f13062e8cd30b77b1962d5df57 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Sat, 18 Jun 2022 02:38:04 +0200 Subject: [PATCH] fix: invalid file request not properly handled [skip release] (#8062) --- changelogs/CHANGELOG_release.md | 7 ++++++ package-lock.json | 2 +- package.json | 2 +- spec/ParseFile.spec.js | 38 +++++++++++++++++++++++++++++++++ src/Routers/FilesRouter.js | 12 ++++++++--- 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/changelogs/CHANGELOG_release.md b/changelogs/CHANGELOG_release.md index 204f33a586..e6b075405a 100644 --- a/changelogs/CHANGELOG_release.md +++ b/changelogs/CHANGELOG_release.md @@ -1,3 +1,10 @@ +## [5.2.3](https://github.com/parse-community/parse-server/compare/5.2.2...5.2.3) (2022-06-17) + + +### Bug Fixes + +* invalid file request not properly handled; this fixes a security vulnerability in which an invalid file request can crash the server ([GHSA-xw6g-jjvf-wwf9](https://github.com/parse-community/parse-server/security/advisories/GHSA-xw6g-jjvf-wwf9)) ([#8060](https://github.com/parse-community/parse-server/issues/8060)) ([5be375d](https://github.com/parse-community/parse-server/commit/5be375dec2fa35425c1003ae81c55995ac72af92)) + ## [5.2.2](https://github.com/parse-community/parse-server/compare/5.2.1...5.2.2) (2022-06-17) diff --git a/package-lock.json b/package-lock.json index 5e51b515a5..f5412bb529 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.2.2", + "version": "5.2.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 26402c479f..9ac0591bbe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.2.2", + "version": "5.2.3", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js index af1de35ee7..281ce45cc2 100644 --- a/spec/ParseFile.spec.js +++ b/spec/ParseFile.spec.js @@ -654,6 +654,44 @@ describe('Parse.File testing', () => { }); }); + describe('getting files', () => { + it('does not crash on file request with invalid app ID', async () => { + const res1 = await request({ + url: 'http://localhost:8378/1/files/invalid-id/invalid-file.txt', + }).catch(e => e); + expect(res1.status).toBe(403); + expect(res1.data).toEqual({ code: 119, error: 'Invalid application ID.' }); + // Ensure server did not crash + const res2 = await request({ url: 'http://localhost:8378/1/health' }); + expect(res2.status).toEqual(200); + expect(res2.data).toEqual({ status: 'ok' }); + }); + + it('does not crash on file request with invalid path', async () => { + const res1 = await request({ + url: 'http://localhost:8378/1/files/invalid-id//invalid-path/%20/invalid-file.txt', + }).catch(e => e); + expect(res1.status).toBe(403); + expect(res1.data).toEqual({ error: 'unauthorized' }); + // Ensure server did not crash + const res2 = await request({ url: 'http://localhost:8378/1/health' }); + expect(res2.status).toEqual(200); + expect(res2.data).toEqual({ status: 'ok' }); + }); + + it('does not crash on file metadata request with invalid app ID', async () => { + const res1 = await request({ + url: `http://localhost:8378/1/files/invalid-id/metadata/invalid-file.txt`, + }); + expect(res1.status).toBe(200); + expect(res1.data).toEqual({}); + // Ensure server did not crash + const res2 = await request({ url: 'http://localhost:8378/1/health' }); + expect(res2.status).toEqual(200); + expect(res2.data).toEqual({ status: 'ok' }); + }); + }); + xdescribe('Gridstore Range tests', () => { it('supports range requests', done => { const headers = { diff --git a/src/Routers/FilesRouter.js b/src/Routers/FilesRouter.js index cccf8e5504..2ea33987ba 100644 --- a/src/Routers/FilesRouter.js +++ b/src/Routers/FilesRouter.js @@ -66,6 +66,12 @@ export class FilesRouter { getHandler(req, res) { const config = Config.get(req.params.appId); + if (!config) { + res.status(403); + const err = new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'Invalid application ID.'); + res.json({ code: err.code, error: err.message }); + return; + } const filesController = config.filesController; const filename = req.params.filename; const contentType = mime.getType(filename); @@ -245,10 +251,10 @@ export class FilesRouter { } async metadataHandler(req, res) { - const config = Config.get(req.params.appId); - const { filesController } = config; - const { filename } = req.params; try { + const config = Config.get(req.params.appId); + const { filesController } = config; + const { filename } = req.params; const data = await filesController.getMetadata(filename); res.status(200); res.json(data);