From 3cf58368abfabb5e82a17ed373fade0e6017c54d Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Fri, 17 Jun 2022 20:33:22 +0200
Subject: [PATCH 1/2] fix

---
 spec/ParseFile.spec.js     | 29 +++++++++++++++++++++++++++++
 src/Routers/FilesRouter.js | 12 +++++++++---
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js
index af1de35ee7..a5963e1b2f 100644
--- a/spec/ParseFile.spec.js
+++ b/spec/ParseFile.spec.js
@@ -654,6 +654,35 @@ describe('Parse.File testing', () => {
     });
   });
 
+  describe('getting files', () => {
+    it('can get invalid file', async () => {
+      const getFile = async () => {
+        try {
+          await request({ url: 'http://localhost:8378/1/files/invalid-id/invalid-file.txt' });
+        } catch (e) {
+          throw new Parse.Error(e.data.code, e.data.error);
+        }
+      };
+      await expectAsync(getFile()).toBeRejectedWith(
+        new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'Invalid appId.')
+      );
+      const { status, data } = await request({ url: 'http://localhost:8378/1/health' });
+      expect(status).toEqual(200);
+      expect(data).toEqual({ status: 'ok' });
+    });
+
+    it('can get invalid metadata', async () => {
+      const metadata = await request({
+        url: `http://localhost:8378/1/files/invalid-id/metadata/invalid-file.txt`,
+      });
+      expect(metadata.status).toBe(200);
+      expect(metadata.data).toEqual({});
+      const { status, data } = await request({ url: 'http://localhost:8378/1/health' });
+      expect(status).toEqual(200);
+      expect(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 c0c7e00f13..bdd86ae59b 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);
@@ -250,10 +256,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);

From 4af79a451f4305a3d2a0520373c2c1ff237206f1 Mon Sep 17 00:00:00 2001
From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com>
Date: Sat, 18 Jun 2022 00:40:35 +0200
Subject: [PATCH 2/2] refactor fix

---
 spec/ParseFile.spec.js | 51 +++++++++++++++++++++++++-----------------
 1 file changed, 30 insertions(+), 21 deletions(-)

diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js
index a5963e1b2f..281ce45cc2 100644
--- a/spec/ParseFile.spec.js
+++ b/spec/ParseFile.spec.js
@@ -655,31 +655,40 @@ describe('Parse.File testing', () => {
   });
 
   describe('getting files', () => {
-    it('can get invalid file', async () => {
-      const getFile = async () => {
-        try {
-          await request({ url: 'http://localhost:8378/1/files/invalid-id/invalid-file.txt' });
-        } catch (e) {
-          throw new Parse.Error(e.data.code, e.data.error);
-        }
-      };
-      await expectAsync(getFile()).toBeRejectedWith(
-        new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'Invalid appId.')
-      );
-      const { status, data } = await request({ url: 'http://localhost:8378/1/health' });
-      expect(status).toEqual(200);
-      expect(data).toEqual({ status: 'ok' });
+    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('can get invalid metadata', async () => {
-      const metadata = await request({
+    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(metadata.status).toBe(200);
-      expect(metadata.data).toEqual({});
-      const { status, data } = await request({ url: 'http://localhost:8378/1/health' });
-      expect(status).toEqual(200);
-      expect(data).toEqual({ status: 'ok' });
+      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' });
     });
   });