fix: Server internal error details leaking in error messages returned to clients (#9937)

This commit is contained in:
Lucas Coratger
2025-11-23 13:51:42 +01:00
committed by GitHub
parent 38c9d2e359
commit 50edb5ab4b
35 changed files with 390 additions and 125 deletions

View File

@@ -3,6 +3,7 @@ import rest from '../rest';
import _ from 'lodash';
import Parse from 'parse/node';
import { promiseEnsureIdempotency } from '../middlewares';
import { createSanitizedError } from '../Error';
const ALLOWED_GET_QUERY_KEYS = [
'keys',
@@ -111,7 +112,7 @@ export class ClassesRouter extends PromiseRouter {
typeof req.body?.objectId === 'string' &&
req.body.objectId.startsWith('role:')
) {
throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'Invalid object ID.');
throw createSanitizedError(Parse.Error.OPERATION_FORBIDDEN, 'Invalid object ID.');
}
return rest.create(
req.config,

View File

@@ -5,6 +5,7 @@ import Config from '../Config';
import logger from '../logger';
const triggers = require('../triggers');
const Utils = require('../Utils');
import { createSanitizedError } from '../Error';
export class FilesRouter {
expressRouter({ maxUploadSize = '20Mb' } = {}) {
@@ -43,7 +44,7 @@ export class FilesRouter {
const config = Config.get(req.params.appId);
if (!config) {
res.status(403);
const err = new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'Invalid application ID.');
const err = createSanitizedError(Parse.Error.OPERATION_FORBIDDEN, 'Invalid application ID.');
res.json({ code: err.code, error: err.message });
return;
}

View File

@@ -3,6 +3,7 @@ import Parse from 'parse/node';
import PromiseRouter from '../PromiseRouter';
import * as middleware from '../middlewares';
import * as triggers from '../triggers';
import { createSanitizedError } from '../Error';
const getConfigFromParams = params => {
const config = new Parse.Config();
@@ -41,9 +42,9 @@ export class GlobalConfigRouter extends PromiseRouter {
async updateGlobalConfig(req) {
if (req.auth.isReadOnly) {
throw new Parse.Error(
throw createSanitizedError(
Parse.Error.OPERATION_FORBIDDEN,
"read-only masterKey isn't allowed to update the config."
"read-only masterKey isn't allowed to update the config.",
);
}
const params = req.body.params || {};

View File

@@ -1,6 +1,7 @@
import Parse from 'parse/node';
import PromiseRouter from '../PromiseRouter';
import * as middleware from '../middlewares';
import { createSanitizedError } from '../Error';
const GraphQLConfigPath = '/graphql-config';
@@ -14,9 +15,9 @@ export class GraphQLRouter extends PromiseRouter {
async updateGraphQLConfig(req) {
if (req.auth.isReadOnly) {
throw new Parse.Error(
throw createSanitizedError(
Parse.Error.OPERATION_FORBIDDEN,
"read-only masterKey isn't allowed to update the GraphQL config."
"read-only masterKey isn't allowed to update the GraphQL config.",
);
}
const data = await req.config.parseGraphQLController.updateGraphQLConfig(req.body?.params || {});

View File

@@ -1,13 +1,14 @@
import PromiseRouter from '../PromiseRouter';
import * as middleware from '../middlewares';
import Parse from 'parse/node';
import { createSanitizedError } from '../Error';
export class PurgeRouter extends PromiseRouter {
handlePurge(req) {
if (req.auth.isReadOnly) {
throw new Parse.Error(
throw createSanitizedError(
Parse.Error.OPERATION_FORBIDDEN,
"read-only masterKey isn't allowed to purge a schema."
"read-only masterKey isn't allowed to purge a schema.",
);
}
return req.config.database

View File

@@ -1,6 +1,7 @@
import PromiseRouter from '../PromiseRouter';
import * as middleware from '../middlewares';
import { Parse } from 'parse/node';
import { createSanitizedError } from '../Error';
export class PushRouter extends PromiseRouter {
mountRoutes() {
@@ -9,9 +10,9 @@ export class PushRouter extends PromiseRouter {
static handlePOST(req) {
if (req.auth.isReadOnly) {
throw new Parse.Error(
throw createSanitizedError(
Parse.Error.OPERATION_FORBIDDEN,
"read-only masterKey isn't allowed to send push notifications."
"read-only masterKey isn't allowed to send push notifications.",
);
}
const pushController = req.config.pushController;

View File

@@ -5,6 +5,7 @@ var Parse = require('parse/node').Parse,
import PromiseRouter from '../PromiseRouter';
import * as middleware from '../middlewares';
import { createSanitizedError } from '../Error';
function classNameMismatchResponse(bodyClass, pathClass) {
throw new Parse.Error(
@@ -72,9 +73,9 @@ export const internalUpdateSchema = async (className, body, config) => {
async function createSchema(req) {
checkIfDefinedSchemasIsUsed(req);
if (req.auth.isReadOnly) {
throw new Parse.Error(
throw createSanitizedError(
Parse.Error.OPERATION_FORBIDDEN,
"read-only masterKey isn't allowed to create a schema."
"read-only masterKey isn't allowed to create a schema.",
);
}
if (req.params.className && req.body?.className) {
@@ -94,9 +95,9 @@ async function createSchema(req) {
function modifySchema(req) {
checkIfDefinedSchemasIsUsed(req);
if (req.auth.isReadOnly) {
throw new Parse.Error(
throw createSanitizedError(
Parse.Error.OPERATION_FORBIDDEN,
"read-only masterKey isn't allowed to update a schema."
"read-only masterKey isn't allowed to update a schema.",
);
}
if (req.body?.className && req.body.className != req.params.className) {
@@ -109,9 +110,9 @@ function modifySchema(req) {
const deleteSchema = req => {
if (req.auth.isReadOnly) {
throw new Parse.Error(
throw createSanitizedError(
Parse.Error.OPERATION_FORBIDDEN,
"read-only masterKey isn't allowed to delete a schema."
"read-only masterKey isn't allowed to delete a schema.",
);
}
if (!SchemaController.classNameIsValid(req.params.className)) {

View File

@@ -17,6 +17,7 @@ import {
import { promiseEnsureIdempotency } from '../middlewares';
import RestWrite from '../RestWrite';
import { logger } from '../logger';
import { createSanitizedError } from '../Error';
export class UsersRouter extends ClassesRouter {
className() {
@@ -171,7 +172,7 @@ export class UsersRouter extends ClassesRouter {
handleMe(req) {
if (!req.info || !req.info.sessionToken) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token');
throw createSanitizedError(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token');
}
const sessionToken = req.info.sessionToken;
return rest
@@ -186,7 +187,7 @@ export class UsersRouter extends ClassesRouter {
)
.then(response => {
if (!response.results || response.results.length == 0 || !response.results[0].user) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token');
throw createSanitizedError(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token');
} else {
const user = response.results[0].user;
// Send token back on the login, because SDKs expect that.
@@ -334,7 +335,10 @@ export class UsersRouter extends ClassesRouter {
*/
async handleLogInAs(req) {
if (!req.auth.isMaster) {
throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'master key is required');
throw createSanitizedError(
Parse.Error.OPERATION_FORBIDDEN,
'master key is required',
);
}
const userId = req.body?.userId || req.query.userId;