Skip to content

Commit a7b5b38

Browse files
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.
1 parent 5452c8f commit a7b5b38

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

spec/Middlewares.spec.js

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ describe('middlewares', () => {
3333
});
3434

3535
it('should use _ContentType if provided', done => {
36+
AppCachePut(fakeReq.body._ApplicationId, {
37+
masterKeyIps: ['127.0.0.1'],
38+
});
3639
expect(fakeReq.headers['content-type']).toEqual(undefined);
3740
const contentType = 'image/jpeg';
3841
fakeReq.body._ContentType = contentType;
@@ -153,25 +156,23 @@ describe('middlewares', () => {
153156
});
154157
fakeReq.ip = '127.0.0.1';
155158
fakeReq.headers['x-parse-master-key'] = 'masterKey';
156-
await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve));
157-
expect(fakeReq.auth.isMaster).toBe(false);
159+
160+
let error;
161+
162+
try {
163+
await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve));
164+
} catch (err) {
165+
error = err;
166+
}
167+
168+
expect(error).toBeDefined();
169+
expect(error.message).toEqual(`unauthorized`);
158170
expect(logger.error).toHaveBeenCalledWith(
159171
`Request using master key rejected as the request IP address '127.0.0.1' is not set in Parse Server option 'masterKeyIps'.`
160172
);
161173
});
162174

163-
it('should not succeed if the ip does not belong to masterKeyIps list', async () => {
164-
AppCachePut(fakeReq.body._ApplicationId, {
165-
masterKey: 'masterKey',
166-
masterKeyIps: ['10.0.0.1'],
167-
});
168-
fakeReq.ip = '127.0.0.1';
169-
fakeReq.headers['x-parse-master-key'] = 'masterKey';
170-
await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve));
171-
expect(fakeReq.auth.isMaster).toBe(false);
172-
});
173-
174-
it('should not succeed if the ip does not belong to maintenanceKeyIps list', async () => {
175+
it('should not succeed and log if the ip does not belong to maintenanceKeyIps list', async () => {
175176
const logger = require('../lib/logger').logger;
176177
spyOn(logger, 'error').and.callFake(() => {});
177178
AppCachePut(fakeReq.body._ApplicationId, {
@@ -180,8 +181,17 @@ describe('middlewares', () => {
180181
});
181182
fakeReq.ip = '10.0.0.2';
182183
fakeReq.headers['x-parse-maintenance-key'] = 'masterKey';
183-
await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve));
184-
expect(fakeReq.auth.isMaintenance).toBe(false);
184+
185+
let error;
186+
187+
try {
188+
await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve));
189+
} catch (err) {
190+
error = err;
191+
}
192+
193+
expect(error).toBeDefined();
194+
expect(error.message).toEqual(`unauthorized`);
185195
expect(logger.error).toHaveBeenCalledWith(
186196
`Request using maintenance key rejected as the request IP address '10.0.0.2' is not set in Parse Server option 'maintenanceKeyIps'.`
187197
);

src/middlewares.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,10 @@ export function handleParseHeaders(req, res, next) {
246246
`Request using master key rejected as the request IP address '${clientIp}' is not set in Parse Server option 'masterKeyIps'.`
247247
);
248248
isMaster = false;
249+
const error = new Error();
250+
error.status = 403;
251+
error.message = `unauthorized`;
252+
throw error;
249253
}
250254

251255
if (isMaster) {

0 commit comments

Comments
 (0)