fix: MongoDB timeout errors unhandled and potentially revealing internal data (#10020)
This commit is contained in:
@@ -27,6 +27,36 @@ const ReadPreference = mongodb.ReadPreference;
|
||||
|
||||
const MongoSchemaCollectionName = '_SCHEMA';
|
||||
|
||||
/**
|
||||
* Determines if a MongoDB error is a transient infrastructure error
|
||||
* (connection pool, network, server selection) as opposed to a query-level error.
|
||||
*/
|
||||
function isTransientError(error) {
|
||||
if (!error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Connection pool, network, and server selection errors
|
||||
const transientErrorNames = [
|
||||
'MongoWaitQueueTimeoutError',
|
||||
'MongoServerSelectionError',
|
||||
'MongoNetworkTimeoutError',
|
||||
'MongoNetworkError',
|
||||
];
|
||||
if (transientErrorNames.includes(error.name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for MongoDB's transient transaction error label
|
||||
if (typeof error.hasErrorLabel === 'function') {
|
||||
if (error.hasErrorLabel('TransientTransactionError')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const storageAdapterAllCollections = mongoAdapter => {
|
||||
return mongoAdapter
|
||||
.connect()
|
||||
@@ -252,6 +282,13 @@ export class MongoStorageAdapter implements StorageAdapter {
|
||||
delete this.connectionPromise;
|
||||
logger.error('Received unauthorized error', { error: error });
|
||||
}
|
||||
|
||||
// Transform infrastructure/transient errors into Parse.Error.INTERNAL_SERVER_ERROR
|
||||
if (isTransientError(error)) {
|
||||
logger.error('Database transient error', error);
|
||||
throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'Database error');
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
|
||||
@@ -378,9 +378,9 @@ export const handleParseSession = async (req, res, next) => {
|
||||
next(error);
|
||||
return;
|
||||
}
|
||||
// TODO: Determine the correct error scenario.
|
||||
// Log full error details internally, but don't expose to client
|
||||
req.config.loggerController.error('error getting auth for sessionToken', error);
|
||||
throw new Parse.Error(Parse.Error.UNKNOWN_ERROR, error);
|
||||
next(new Parse.Error(Parse.Error.UNKNOWN_ERROR, 'Unknown error'));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user