mirror of
https://github.com/parse-community/parse-server
synced 2026-08-09 13:03:18 +00:00
feat: Add security check for server option mountPlayground for GraphQL development (#10103)
This commit is contained in:
@@ -822,7 +822,7 @@ $ parse-server --appId APPLICATION_ID --masterKey MASTER_KEY --databaseURI mongo
|
||||
|
||||
After starting the server, you can visit http://localhost:1337/playground in your browser to start playing with your GraphQL API.
|
||||
|
||||
**_Note:_** Do **_NOT_** use --mountPlayground option in production. [Parse Dashboard](https://github.com/parse-community/parse-dashboard) has a built-in GraphQL Playground and it is the recommended option for production apps.
|
||||
**_Note:_** Do **_NOT_** use --mountPlayground option in production. The GraphQL Playground exposes the master key in the browser page. [Parse Dashboard](https://github.com/parse-community/parse-dashboard) has a built-in GraphQL Playground and is the recommended option for production apps.
|
||||
|
||||
### Using Docker
|
||||
|
||||
@@ -845,7 +845,7 @@ $ docker run --name my-parse-server --link my-mongo:mongo -v config-vol:/parse-s
|
||||
|
||||
After starting the server, you can visit http://localhost:1337/playground in your browser to start playing with your GraphQL API.
|
||||
|
||||
**_Note:_** Do **_NOT_** use --mountPlayground option in production. [Parse Dashboard](https://github.com/parse-community/parse-dashboard) has a built-in GraphQL Playground and it is the recommended option for production apps.
|
||||
**_Note:_** Do **_NOT_** use --mountPlayground option in production. The GraphQL Playground exposes the master key in the browser page. [Parse Dashboard](https://github.com/parse-community/parse-dashboard) has a built-in GraphQL Playground and is the recommended option for production apps.
|
||||
|
||||
### Using Express.js
|
||||
|
||||
@@ -899,7 +899,7 @@ $ node index.js
|
||||
|
||||
After starting the app, you can visit http://localhost:1337/playground in your browser to start playing with your GraphQL API.
|
||||
|
||||
**_Note:_** Do **_NOT_** mount the GraphQL Playground in production. [Parse Dashboard](https://github.com/parse-community/parse-dashboard) has a built-in GraphQL Playground and it is the recommended option for production apps.
|
||||
**_Note:_** Do **_NOT_** mount the GraphQL Playground in production. The GraphQL Playground exposes the master key in the browser page. [Parse Dashboard](https://github.com/parse-community/parse-dashboard) has a built-in GraphQL Playground and is the recommended option for production apps.
|
||||
|
||||
## Checking the API health
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ describe('Security Check Groups', () => {
|
||||
config.allowClientClassCreation = false;
|
||||
config.enableInsecureAuthAdapters = false;
|
||||
config.graphQLPublicIntrospection = false;
|
||||
config.mountPlayground = false;
|
||||
await reconfigureServer(config);
|
||||
|
||||
const group = new CheckGroupServerConfig();
|
||||
@@ -43,6 +44,7 @@ describe('Security Check Groups', () => {
|
||||
expect(group.checks()[2].checkState()).toBe(CheckState.success);
|
||||
expect(group.checks()[4].checkState()).toBe(CheckState.success);
|
||||
expect(group.checks()[5].checkState()).toBe(CheckState.success);
|
||||
expect(group.checks()[6].checkState()).toBe(CheckState.success);
|
||||
});
|
||||
|
||||
it('checks fail correctly', async () => {
|
||||
@@ -51,6 +53,7 @@ describe('Security Check Groups', () => {
|
||||
config.allowClientClassCreation = true;
|
||||
config.enableInsecureAuthAdapters = true;
|
||||
config.graphQLPublicIntrospection = true;
|
||||
config.mountPlayground = true;
|
||||
await reconfigureServer(config);
|
||||
|
||||
const group = new CheckGroupServerConfig();
|
||||
@@ -60,6 +63,7 @@ describe('Security Check Groups', () => {
|
||||
expect(group.checks()[2].checkState()).toBe(CheckState.fail);
|
||||
expect(group.checks()[4].checkState()).toBe(CheckState.fail);
|
||||
expect(group.checks()[5].checkState()).toBe(CheckState.fail);
|
||||
expect(group.checks()[6].checkState()).toBe(CheckState.fail);
|
||||
});
|
||||
|
||||
it_only_db('mongo')('checks succeed correctly (MongoDB specific)', async () => {
|
||||
@@ -69,7 +73,7 @@ describe('Security Check Groups', () => {
|
||||
|
||||
const group = new CheckGroupServerConfig();
|
||||
await group.run();
|
||||
expect(group.checks()[6].checkState()).toBe(CheckState.success);
|
||||
expect(group.checks()[7].checkState()).toBe(CheckState.success);
|
||||
});
|
||||
|
||||
it_only_db('mongo')('checks fail correctly (MongoDB specific)', async () => {
|
||||
@@ -79,7 +83,7 @@ describe('Security Check Groups', () => {
|
||||
|
||||
const group = new CheckGroupServerConfig();
|
||||
await group.run();
|
||||
expect(group.checks()[6].checkState()).toBe(CheckState.fail);
|
||||
expect(group.checks()[7].checkState()).toBe(CheckState.fail);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -404,7 +404,7 @@ module.exports.ParseServerOptions = {
|
||||
},
|
||||
mountPlayground: {
|
||||
env: 'PARSE_SERVER_MOUNT_PLAYGROUND',
|
||||
help: 'Mounts the GraphQL Playground - never use this option in production',
|
||||
help: 'Mounts the GraphQL Playground which exposes the master key in the browser - never use this option in production',
|
||||
action: parsers.booleanParser,
|
||||
default: false,
|
||||
},
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@
|
||||
* @property {Union} middleware middleware for express server, can be string or function
|
||||
* @property {Boolean} mountGraphQL Mounts the GraphQL endpoint
|
||||
* @property {String} mountPath Mount path for the server, defaults to /parse
|
||||
* @property {Boolean} mountPlayground Mounts the GraphQL Playground - never use this option in production
|
||||
* @property {Boolean} mountPlayground Mounts the GraphQL Playground which exposes the master key in the browser - never use this option in production
|
||||
* @property {Number} objectIdSize Sets the number of characters in generated object id's, default 10
|
||||
* @property {PagesOptions} pages The options for pages such as password reset and email verification.
|
||||
* @property {PasswordPolicyOptions} passwordPolicy The password policy for enforcing password related rules.
|
||||
|
||||
@@ -339,7 +339,7 @@ export interface ParseServerOptions {
|
||||
:ENV: PARSE_SERVER_GRAPHQL_PUBLIC_INTROSPECTION
|
||||
:DEFAULT: false */
|
||||
graphQLPublicIntrospection: ?boolean;
|
||||
/* Mounts the GraphQL Playground - never use this option in production
|
||||
/* Mounts the GraphQL Playground which exposes the master key in the browser - never use this option in production
|
||||
:ENV: PARSE_SERVER_MOUNT_PLAYGROUND
|
||||
:DEFAULT: false */
|
||||
mountPlayground: ?boolean;
|
||||
|
||||
@@ -458,6 +458,9 @@ class ParseServer {
|
||||
|
||||
if (options.mountPlayground) {
|
||||
parseGraphQLServer.applyPlayground(app);
|
||||
logging.getLogger().warn(
|
||||
'GraphQL Playground is enabled and exposes the master key in the browser. The playground is a developer tool and should not be used in production. Use Parse Dashboard for production environments.'
|
||||
);
|
||||
}
|
||||
}
|
||||
const server = await new Promise(resolve => {
|
||||
|
||||
@@ -90,6 +90,18 @@ class CheckGroupServerConfig extends CheckGroup {
|
||||
}
|
||||
},
|
||||
}),
|
||||
new Check({
|
||||
title: 'GraphQL Playground disabled',
|
||||
warning:
|
||||
'GraphQL Playground is enabled and exposes the master key in the browser page.',
|
||||
solution:
|
||||
"Change Parse Server configuration to 'mountPlayground: false'. Use Parse Dashboard for GraphQL exploration in production.",
|
||||
check: () => {
|
||||
if (config.mountPlayground) {
|
||||
throw 1;
|
||||
}
|
||||
},
|
||||
}),
|
||||
new Check({
|
||||
title: 'Public database explain disabled',
|
||||
warning:
|
||||
|
||||
Reference in New Issue
Block a user