Skip to content

Commit 0b71afe

Browse files
committed
fix: requestComplexity opt in and new defaults
1 parent bc9aa37 commit 0b71afe

File tree

5 files changed

+44
-4
lines changed

5 files changed

+44
-4
lines changed

DEPRECATIONS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ The following is a list of deprecations, according to the [Deprecation Policy](h
2121
| DEPPS15 | Config option `readOnlyMasterKeyIps` defaults to `['127.0.0.1', '::1']` | [#10115](https://github.com/parse-community/parse-server/pull/10115) | 9.5.0 (2026) | 10.0.0 (2027) | deprecated | - |
2222
| DEPPS16 | Remove config option `mountPlayground` | [#10110](https://github.com/parse-community/parse-server/issues/10110) | 9.5.0 (2026) | 10.0.0 (2027) | deprecated | - |
2323
| DEPPS17 | Remove config option `playgroundPath` | [#10110](https://github.com/parse-community/parse-server/issues/10110) | 9.5.0 (2026) | 10.0.0 (2027) | deprecated | - |
24+
| DEPPS18 | Config option `requestComplexity` defaults to enabled with limits | TBD | 9.6.0 (2026) | 10.0.0 (2027) | deprecated | - |
2425

2526
[i_deprecation]: ## "The version and date of the deprecation."
2627
[i_change]: ## "The version and date of the planned change."

spec/RequestComplexity.spec.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,31 @@ describe('request complexity', () => {
116116
expect(config.requestComplexity.graphQLFields).toBe(200);
117117
});
118118

119-
it('should apply full defaults when not configured', async () => {
119+
it('should have requestComplexity undefined when not configured', async () => {
120120
await reconfigureServer({});
121121
const config = Config.get('test');
122+
expect(config.requestComplexity).toBeUndefined();
123+
});
124+
125+
it('should apply no limits when requestComplexity is undefined', async () => {
126+
await reconfigureServer({});
127+
const config = Config.get('test');
128+
expect(config.requestComplexity).toBeUndefined();
129+
130+
const where = buildNestedInQuery(15);
131+
await expectAsync(
132+
rest.find(config, auth.nobody(config), '_User', where)
133+
).toBeResolved();
134+
135+
const includes = Array.from({ length: 100 }, (_, i) => `field${i}`).join(',');
136+
await expectAsync(
137+
rest.find(config, auth.nobody(config), '_User', {}, { include: includes })
138+
).toBeResolved();
139+
});
140+
141+
it('should apply full defaults when empty object is passed', async () => {
142+
await reconfigureServer({ requestComplexity: {} });
143+
const config = Config.get('test');
122144
expect(config.requestComplexity).toEqual({
123145
includeDepth: 5,
124146
includeCount: 50,
@@ -127,6 +149,18 @@ describe('request complexity', () => {
127149
graphQLFields: 200,
128150
});
129151
});
152+
153+
it('should log deprecation warning when requestComplexity is not set', async () => {
154+
const Deprecator = require('../lib/Deprecator/Deprecator');
155+
const logSpy = spyOn(Deprecator, '_logOption').and.callThrough();
156+
await reconfigureServer({});
157+
expect(logSpy).toHaveBeenCalledWith(
158+
jasmine.objectContaining({
159+
optionKey: 'requestComplexity',
160+
changeNewDefault: jasmine.stringMatching(/includeDepth.*10/),
161+
})
162+
);
163+
});
130164
});
131165

132166
describe('subquery depth', () => {

src/Deprecator/Deprecations.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,9 @@ module.exports = [
4141
changeNewKey: '',
4242
solution: "Use Parse Dashboard as GraphQL IDE or configure a third-party GraphQL client such as Apollo Sandbox, GraphiQL, or Insomnia with custom request headers.",
4343
},
44+
{
45+
optionKey: 'requestComplexity',
46+
changeNewDefault: '{"includeDepth":10,"includeCount":100,"subqueryDepth":10,"graphQLDepth":20,"graphQLFields":200}',
47+
solution: "Set 'requestComplexity' to the limits you want to enforce, or to the above object to opt-in to the future default behavior.",
48+
},
4449
];

src/Options/Definitions.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,10 +500,10 @@ module.exports.ParseServerOptions = {
500500
},
501501
requestComplexity: {
502502
env: 'PARSE_SERVER_REQUEST_COMPLEXITY',
503-
help: 'Options to limit the complexity of requests to prevent denial-of-service attacks. Limits are enforced for all requests except those using the master or maintenance key. Each property can be set to `-1` to disable that specific limit.',
503+
help: 'Options to limit the complexity of requests to prevent denial-of-service attacks. Limits are enforced for all requests except those using the master or maintenance key. Each property can be set to `-1` to disable that specific limit. Disabled by default in the current version; will be enabled by default with specific limits in the next major version.',
504504
action: parsers.objectParser,
505505
type: 'RequestComplexityOptions',
506-
default: {},
506+
default: undefined,
507507
},
508508
requestContextMiddleware: {
509509
env: 'PARSE_SERVER_REQUEST_CONTEXT_MIDDLEWARE',

src/Security/CheckGroups/CheckGroupServerConfig.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ class CheckGroupServerConfig extends CheckGroup {
143143
check: () => {
144144
const rc = config.requestComplexity;
145145
if (!rc) {
146-
throw 1;
146+
return;
147147
}
148148
const values = [rc.includeDepth, rc.includeCount, rc.subqueryDepth, rc.graphQLDepth, rc.graphQLFields];
149149
if (values.some(v => v === -1)) {

0 commit comments

Comments
 (0)