Skip to content

Commit 5f42322

Browse files
authored
fix: 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](GHSA-xw6g-jjvf-wwf9)) (#8059)
1 parent ad680bd commit 5f42322

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

spec/ParseFile.spec.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,44 @@ describe('Parse.File testing', () => {
623623
});
624624
});
625625

626+
describe('getting files', () => {
627+
it('does not crash on file request with invalid app ID', async () => {
628+
const res1 = await request({
629+
url: 'http://localhost:8378/1/files/invalid-id/invalid-file.txt',
630+
}).catch(e => e);
631+
expect(res1.status).toBe(403);
632+
expect(res1.data).toEqual({ code: 119, error: 'Invalid application ID.' });
633+
// Ensure server did not crash
634+
const res2 = await request({ url: 'http://localhost:8378/1/health' });
635+
expect(res2.status).toEqual(200);
636+
expect(res2.data).toEqual({ status: 'ok' });
637+
});
638+
639+
it('does not crash on file request with invalid path', async () => {
640+
const res1 = await request({
641+
url: 'http://localhost:8378/1/files/invalid-id//invalid-path/%20/invalid-file.txt',
642+
}).catch(e => e);
643+
expect(res1.status).toBe(403);
644+
expect(res1.data).toEqual({ error: 'unauthorized' });
645+
// Ensure server did not crash
646+
const res2 = await request({ url: 'http://localhost:8378/1/health' });
647+
expect(res2.status).toEqual(200);
648+
expect(res2.data).toEqual({ status: 'ok' });
649+
});
650+
651+
it('does not crash on file metadata request with invalid app ID', async () => {
652+
const res1 = await request({
653+
url: `http://localhost:8378/1/files/invalid-id/metadata/invalid-file.txt`,
654+
});
655+
expect(res1.status).toBe(200);
656+
expect(res1.data).toEqual({});
657+
// Ensure server did not crash
658+
const res2 = await request({ url: 'http://localhost:8378/1/health' });
659+
expect(res2.status).toEqual(200);
660+
expect(res2.data).toEqual({ status: 'ok' });
661+
});
662+
});
663+
626664
xdescribe('Gridstore Range tests', () => {
627665
it('supports range requests', done => {
628666
const headers = {

src/Routers/FilesRouter.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ export class FilesRouter {
6666

6767
getHandler(req, res) {
6868
const config = Config.get(req.params.appId);
69+
if (!config) {
70+
res.status(403);
71+
const err = new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'Invalid application ID.');
72+
res.json({ code: err.code, error: err.message });
73+
return;
74+
}
6975
const filesController = config.filesController;
7076
const filename = req.params.filename;
7177
const contentType = mime.getType(filename);
@@ -222,10 +228,10 @@ export class FilesRouter {
222228
}
223229

224230
async metadataHandler(req, res) {
225-
const config = Config.get(req.params.appId);
226-
const { filesController } = config;
227-
const { filename } = req.params;
228231
try {
232+
const config = Config.get(req.params.appId);
233+
const { filesController } = config;
234+
const { filename } = req.params;
229235
const data = await filesController.getMetadata(filename);
230236
res.status(200);
231237
res.json(data);

0 commit comments

Comments
 (0)