From a7b5b38418cbed9be3f4a7665f25b97f592663e1 Mon Sep 17 00:00:00 2001 From: EhsanParsania <75175231+EhsanParsania@users.noreply.github.com> Date: Fri, 1 Mar 2024 21:07:07 +0330 Subject: [PATCH] fix: Deny request if master key is not set in Parse Server option `masterKeyIps` regardless of ACL and CLP (#8957) BREAKING CHANGE: A request using the master key will now be rejected as unauthorized if the IP from which the request originates is not set in the Parse Server option `masterKeyIps`, even if the request does not require the master key permission, for example for a public object in a public class class. --- spec/Middlewares.spec.js | 42 +++++++++++++++++++++++++--------------- src/middlewares.js | 4 ++++ 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/spec/Middlewares.spec.js b/spec/Middlewares.spec.js index 7ec50bd434..af547ec77a 100644 --- a/spec/Middlewares.spec.js +++ b/spec/Middlewares.spec.js @@ -33,6 +33,9 @@ describe('middlewares', () => { }); it('should use _ContentType if provided', done => { + AppCachePut(fakeReq.body._ApplicationId, { + masterKeyIps: ['127.0.0.1'], + }); expect(fakeReq.headers['content-type']).toEqual(undefined); const contentType = 'image/jpeg'; fakeReq.body._ContentType = contentType; @@ -153,25 +156,23 @@ describe('middlewares', () => { }); fakeReq.ip = '127.0.0.1'; fakeReq.headers['x-parse-master-key'] = 'masterKey'; - await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve)); - expect(fakeReq.auth.isMaster).toBe(false); + + let error; + + try { + await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve)); + } catch (err) { + error = err; + } + + expect(error).toBeDefined(); + expect(error.message).toEqual(`unauthorized`); expect(logger.error).toHaveBeenCalledWith( `Request using master key rejected as the request IP address '127.0.0.1' is not set in Parse Server option 'masterKeyIps'.` ); }); - it('should not succeed if the ip does not belong to masterKeyIps list', async () => { - AppCachePut(fakeReq.body._ApplicationId, { - masterKey: 'masterKey', - masterKeyIps: ['10.0.0.1'], - }); - fakeReq.ip = '127.0.0.1'; - fakeReq.headers['x-parse-master-key'] = 'masterKey'; - await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve)); - expect(fakeReq.auth.isMaster).toBe(false); - }); - - it('should not succeed if the ip does not belong to maintenanceKeyIps list', async () => { + it('should not succeed and log if the ip does not belong to maintenanceKeyIps list', async () => { const logger = require('../lib/logger').logger; spyOn(logger, 'error').and.callFake(() => {}); AppCachePut(fakeReq.body._ApplicationId, { @@ -180,8 +181,17 @@ describe('middlewares', () => { }); fakeReq.ip = '10.0.0.2'; fakeReq.headers['x-parse-maintenance-key'] = 'masterKey'; - await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve)); - expect(fakeReq.auth.isMaintenance).toBe(false); + + let error; + + try { + await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve)); + } catch (err) { + error = err; + } + + expect(error).toBeDefined(); + expect(error.message).toEqual(`unauthorized`); expect(logger.error).toHaveBeenCalledWith( `Request using maintenance key rejected as the request IP address '10.0.0.2' is not set in Parse Server option 'maintenanceKeyIps'.` ); diff --git a/src/middlewares.js b/src/middlewares.js index d4edb37760..880315253f 100644 --- a/src/middlewares.js +++ b/src/middlewares.js @@ -246,6 +246,10 @@ export function handleParseHeaders(req, res, next) { `Request using master key rejected as the request IP address '${clientIp}' is not set in Parse Server option 'masterKeyIps'.` ); isMaster = false; + const error = new Error(); + error.status = 403; + error.message = `unauthorized`; + throw error; } if (isMaster) {