22 Commits

Author SHA1 Message Date
semantic-release-bot
84959c69e5 chore(release): 9.2.0 [skip ci]
# [9.2.0](https://github.com/parse-community/parse-server/compare/9.1.1...9.2.0) (2026-02-05)

### Bug Fixes

* MongoDB timeout errors unhandled and potentially revealing internal data ([#10020](https://github.com/parse-community/parse-server/issues/10020)) ([1d3336d](1d3336d128))
* Security upgrade @apollo/server from 5.0.0 to 5.4.0 ([#10035](https://github.com/parse-community/parse-server/issues/10035)) ([9f368ff](9f368ff9ca))

### Features

* Add option `databaseOptions.clientMetadata` to send custom metadata to database server for logging and debugging ([#10017](https://github.com/parse-community/parse-server/issues/10017)) ([756c204](756c204220))
* Upgrade mongodb from 6.20.0 to 7.0.0 ([#10027](https://github.com/parse-community/parse-server/issues/10027)) ([14b3fce](14b3fce203))
* Upgrade to parse 8.0.3 and @parse/push-adapter 8.2.0 ([#10021](https://github.com/parse-community/parse-server/issues/10021)) ([9833fdb](9833fdb111))
2026-02-05 13:10:33 +00:00
Manuel
88b6977333 build: Release (#10036) 2026-02-05 13:09:31 +00:00
GitHub Actions
88fa87aa28 empty commit to trigger CI 2026-02-05 12:45:46 +00:00
semantic-release-bot
e70303d5c3 chore(release): 9.2.0-alpha.5 [skip ci]
# [9.2.0-alpha.5](https://github.com/parse-community/parse-server/compare/9.2.0-alpha.4...9.2.0-alpha.5) (2026-02-05)

### Bug Fixes

* Security upgrade @apollo/server from 5.0.0 to 5.4.0 ([#10035](https://github.com/parse-community/parse-server/issues/10035)) ([9f368ff](9f368ff9ca))
2026-02-05 12:43:01 +00:00
dependabot[bot]
9f368ff9ca fix: Security upgrade @apollo/server from 5.0.0 to 5.4.0 (#10035) 2026-02-05 12:42:13 +00:00
dependabot[bot]
b87eaea12f refactor: Bump cors from 2.8.5 to 2.8.6 (#10033) 2026-02-04 17:55:30 +00:00
Corey
6cfbcfd139 refactor: Upgrade pg-promise from 12.2.0 to 12.6.0 (#10031) 2026-02-04 00:55:44 +00:00
dependabot[bot]
c21e8952ae refactor: Bump m from 1.9.1 to 1.10.0 (#10029) 2026-01-31 02:22:17 +01:00
dependabot[bot]
f6d78005d4 refactor: Bump @babel/eslint-parser from 7.28.0 to 7.28.6 (#10028) 2026-01-30 19:16:58 +01:00
dependabot[bot]
b42a0ee61d refactor: Bump winston from 3.17.0 to 3.19.0 (#10023) 2026-01-29 20:29:19 +01:00
semantic-release-bot
2457da9e15 chore(release): 9.2.0-alpha.4 [skip ci]
# [9.2.0-alpha.4](https://github.com/parse-community/parse-server/compare/9.2.0-alpha.3...9.2.0-alpha.4) (2026-01-29)

### Features

* Upgrade mongodb from 6.20.0 to 7.0.0 ([#10027](https://github.com/parse-community/parse-server/issues/10027)) ([14b3fce](14b3fce203))
2026-01-29 12:52:21 +00:00
dependabot[bot]
14b3fce203 feat: Upgrade mongodb from 6.20.0 to 7.0.0 (#10027) 2026-01-29 13:51:32 +01:00
dependabot[bot]
73e21e77c7 refactor: Bump bcryptjs from 3.0.2 to 3.0.3 (#10022) 2026-01-27 20:09:50 +01:00
Manuel
c015864293 docs: Simplify PR template (#10026) 2026-01-27 18:07:02 +01:00
semantic-release-bot
f2babb2ac4 chore(release): 9.2.0-alpha.3 [skip ci]
# [9.2.0-alpha.3](https://github.com/parse-community/parse-server/compare/9.2.0-alpha.2...9.2.0-alpha.3) (2026-01-27)

### Features

* Upgrade to parse 8.0.3 and @parse/push-adapter 8.2.0 ([#10021](https://github.com/parse-community/parse-server/issues/10021)) ([9833fdb](9833fdb111))
2026-01-27 17:02:53 +00:00
Manuel
9833fdb111 feat: Upgrade to parse 8.0.3 and @parse/push-adapter 8.2.0 (#10021) 2026-01-27 18:01:57 +01:00
dependabot[bot]
dc866bed3b refactor: Bump lodash from 4.17.21 to 4.17.23 (#10016) 2026-01-25 19:46:36 +01:00
dependabot[bot]
906ccc3e29 refactor: Bump lodash-es from 4.17.21 to 4.17.23 (#10015) 2026-01-25 19:25:54 +01:00
dependabot[bot]
5c00a6ab1b refactor: Bump typescript-eslint from 8.33.1 to 8.53.0 (#10011) 2026-01-25 18:58:41 +01:00
dependabot[bot]
5d28fcba0c refactor: Bump @babel/core from 7.27.4 to 7.28.6 (#10012) 2026-01-25 18:58:15 +01:00
semantic-release-bot
db3cbb2113 chore(release): 9.2.0-alpha.2 [skip ci]
# [9.2.0-alpha.2](https://github.com/parse-community/parse-server/compare/9.2.0-alpha.1...9.2.0-alpha.2) (2026-01-24)

### Bug Fixes

* MongoDB timeout errors unhandled and potentially revealing internal data ([#10020](https://github.com/parse-community/parse-server/issues/10020)) ([1d3336d](1d3336d128))
2026-01-24 23:15:52 +00:00
Manuel
1d3336d128 fix: MongoDB timeout errors unhandled and potentially revealing internal data (#10020) 2026-01-25 00:15:01 +01:00
10 changed files with 1575 additions and 1212 deletions

View File

@@ -2,10 +2,9 @@
- Report security issues [confidentially](https://github.com/parse-community/parse-server/security/policy).
- Any contribution is under this [license](https://github.com/parse-community/parse-server/blob/alpha/LICENSE).
- Link this pull request to an [issue](https://github.com/parse-community/parse-server/issues?q=is%3Aissue).
## Issue
<!-- Add the link to the issue that this PR closes. -->
<!-- Describe the issue. -->
Closes: FILL_THIS_OUT
@@ -13,7 +12,7 @@ Closes: FILL_THIS_OUT
<!-- Describe the changes in this PR. -->
## Tasks
<!-- Delete tasks that don't apply. -->
<!-- Check completed tasks and delete tasks that don't apply. -->
- [ ] Add tests
- [ ] Add changes to documentation (guides, repository pages, code comments)

View File

@@ -1,3 +1,31 @@
# [9.2.0-alpha.5](https://github.com/parse-community/parse-server/compare/9.2.0-alpha.4...9.2.0-alpha.5) (2026-02-05)
### Bug Fixes
* Security upgrade @apollo/server from 5.0.0 to 5.4.0 ([#10035](https://github.com/parse-community/parse-server/issues/10035)) ([9f368ff](https://github.com/parse-community/parse-server/commit/9f368ff9ca322c61cdcfab735e5b5240d1c8f917))
# [9.2.0-alpha.4](https://github.com/parse-community/parse-server/compare/9.2.0-alpha.3...9.2.0-alpha.4) (2026-01-29)
### Features
* Upgrade mongodb from 6.20.0 to 7.0.0 ([#10027](https://github.com/parse-community/parse-server/issues/10027)) ([14b3fce](https://github.com/parse-community/parse-server/commit/14b3fce203be0abaf29c27c123cba47f35d09c68))
# [9.2.0-alpha.3](https://github.com/parse-community/parse-server/compare/9.2.0-alpha.2...9.2.0-alpha.3) (2026-01-27)
### Features
* Upgrade to parse 8.0.3 and @parse/push-adapter 8.2.0 ([#10021](https://github.com/parse-community/parse-server/issues/10021)) ([9833fdb](https://github.com/parse-community/parse-server/commit/9833fdb111c373dc75fc74ea5f9209408186a475))
# [9.2.0-alpha.2](https://github.com/parse-community/parse-server/compare/9.2.0-alpha.1...9.2.0-alpha.2) (2026-01-24)
### Bug Fixes
* MongoDB timeout errors unhandled and potentially revealing internal data ([#10020](https://github.com/parse-community/parse-server/issues/10020)) ([1d3336d](https://github.com/parse-community/parse-server/commit/1d3336d128671c974b419b9b34db35ada7d1a44d))
# [9.2.0-alpha.1](https://github.com/parse-community/parse-server/compare/9.1.1...9.2.0-alpha.1) (2026-01-24)

View File

@@ -1,3 +1,17 @@
# [9.2.0](https://github.com/parse-community/parse-server/compare/9.1.1...9.2.0) (2026-02-05)
### Bug Fixes
* MongoDB timeout errors unhandled and potentially revealing internal data ([#10020](https://github.com/parse-community/parse-server/issues/10020)) ([1d3336d](https://github.com/parse-community/parse-server/commit/1d3336d128671c974b419b9b34db35ada7d1a44d))
* Security upgrade @apollo/server from 5.0.0 to 5.4.0 ([#10035](https://github.com/parse-community/parse-server/issues/10035)) ([9f368ff](https://github.com/parse-community/parse-server/commit/9f368ff9ca322c61cdcfab735e5b5240d1c8f917))
### Features
* Add option `databaseOptions.clientMetadata` to send custom metadata to database server for logging and debugging ([#10017](https://github.com/parse-community/parse-server/issues/10017)) ([756c204](https://github.com/parse-community/parse-server/commit/756c204220a2c7be3770b7d4a49f11e8903323db))
* Upgrade mongodb from 6.20.0 to 7.0.0 ([#10027](https://github.com/parse-community/parse-server/issues/10027)) ([14b3fce](https://github.com/parse-community/parse-server/commit/14b3fce203be0abaf29c27c123cba47f35d09c68))
* Upgrade to parse 8.0.3 and @parse/push-adapter 8.2.0 ([#10021](https://github.com/parse-community/parse-server/issues/10021)) ([9833fdb](https://github.com/parse-community/parse-server/commit/9833fdb111c373dc75fc74ea5f9209408186a475))
## [9.1.1](https://github.com/parse-community/parse-server/compare/9.1.0...9.1.1) (2025-12-16)

2544
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "parse-server",
"version": "9.2.0-alpha.1",
"version": "9.2.0",
"description": "An express module providing a Parse-compatible API server",
"main": "lib/index.js",
"repository": {
@@ -20,16 +20,16 @@
],
"license": "Apache-2.0",
"dependencies": {
"@apollo/server": "5.0.0",
"@apollo/server": "5.4.0",
"@as-integrations/express5": "1.1.2",
"@graphql-tools/merge": "9.0.24",
"@graphql-tools/schema": "10.0.23",
"@graphql-tools/utils": "10.8.6",
"@parse/fs-files-adapter": "3.0.0",
"@parse/push-adapter": "8.1.0",
"bcryptjs": "3.0.2",
"@parse/push-adapter": "8.2.0",
"bcryptjs": "3.0.3",
"commander": "14.0.2",
"cors": "2.8.5",
"cors": "2.8.6",
"deepcopy": "2.1.0",
"express": "5.2.1",
"express-rate-limit": "7.5.1",
@@ -42,16 +42,16 @@
"jsonwebtoken": "9.0.2",
"jwks-rsa": "3.2.0",
"ldapjs": "3.0.7",
"lodash": "4.17.21",
"lodash": "4.17.23",
"lru-cache": "10.4.0",
"mime": "4.0.7",
"mongodb": "6.20.0",
"mongodb": "7.0.0",
"mustache": "4.2.0",
"otpauth": "9.4.0",
"parse": "8.0.0",
"parse": "8.0.3",
"path-to-regexp": "8.3.0",
"pg-monitor": "3.0.0",
"pg-promise": "12.2.0",
"pg-promise": "12.6.0",
"pluralize": "8.0.0",
"punycode": "2.3.1",
"rate-limit-redis": "4.2.0",
@@ -60,7 +60,7 @@
"subscriptions-transport-ws": "0.11.0",
"tv4": "1.3.0",
"uuid": "11.1.0",
"winston": "3.17.0",
"winston": "3.19.0",
"winston-daily-rotate-file": "5.0.0",
"ws": "8.18.2"
},
@@ -68,8 +68,8 @@
"@actions/core": "1.11.1",
"@apollo/client": "3.13.8",
"@babel/cli": "7.27.0",
"@babel/core": "7.27.4",
"@babel/eslint-parser": "7.28.0",
"@babel/core": "7.28.6",
"@babel/eslint-parser": "7.28.6",
"@babel/plugin-proposal-object-rest-spread": "7.20.7",
"@babel/plugin-transform-flow-strip-types": "7.26.5",
"@babel/preset-env": "7.27.2",
@@ -97,7 +97,7 @@
"jsdoc": "4.0.4",
"jsdoc-babel": "0.5.0",
"lint-staged": "16.1.0",
"m": "1.9.1",
"m": "1.10.0",
"madge": "8.0.0",
"mock-files-adapter": "file:spec/dependencies/mock-files-adapter",
"mock-mail-adapter": "file:spec/dependencies/mock-mail-adapter",
@@ -108,7 +108,7 @@
"prettier": "2.0.5",
"semantic-release": "24.2.5",
"typescript": "5.8.3",
"typescript-eslint": "8.33.1",
"typescript-eslint": "8.53.1",
"yaml": "2.8.0"
},
"scripts": {

View File

@@ -1064,6 +1064,129 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
});
});
describe('transient error handling', () => {
it('should transform MongoWaitQueueTimeoutError to Parse.Error.INTERNAL_SERVER_ERROR', async () => {
const adapter = new MongoStorageAdapter({ uri: databaseURI });
await adapter.connect();
// Create a mock error with the MongoWaitQueueTimeoutError name
const mockError = new Error('Timed out while checking out a connection from connection pool');
mockError.name = 'MongoWaitQueueTimeoutError';
try {
adapter.handleError(mockError);
fail('Expected handleError to throw');
} catch (error) {
expect(error instanceof Parse.Error).toBe(true);
expect(error.code).toBe(Parse.Error.INTERNAL_SERVER_ERROR);
expect(error.message).toBe('Database error');
}
});
it('should transform MongoServerSelectionError to Parse.Error.INTERNAL_SERVER_ERROR', async () => {
const adapter = new MongoStorageAdapter({ uri: databaseURI });
await adapter.connect();
const mockError = new Error('Server selection timed out');
mockError.name = 'MongoServerSelectionError';
try {
adapter.handleError(mockError);
fail('Expected handleError to throw');
} catch (error) {
expect(error instanceof Parse.Error).toBe(true);
expect(error.code).toBe(Parse.Error.INTERNAL_SERVER_ERROR);
expect(error.message).toBe('Database error');
}
});
it('should transform MongoNetworkTimeoutError to Parse.Error.INTERNAL_SERVER_ERROR', async () => {
const adapter = new MongoStorageAdapter({ uri: databaseURI });
await adapter.connect();
const mockError = new Error('Network timeout');
mockError.name = 'MongoNetworkTimeoutError';
try {
adapter.handleError(mockError);
fail('Expected handleError to throw');
} catch (error) {
expect(error instanceof Parse.Error).toBe(true);
expect(error.code).toBe(Parse.Error.INTERNAL_SERVER_ERROR);
expect(error.message).toBe('Database error');
}
});
it('should transform MongoNetworkError to Parse.Error.INTERNAL_SERVER_ERROR', async () => {
const adapter = new MongoStorageAdapter({ uri: databaseURI });
await adapter.connect();
const mockError = new Error('Network error');
mockError.name = 'MongoNetworkError';
try {
adapter.handleError(mockError);
fail('Expected handleError to throw');
} catch (error) {
expect(error instanceof Parse.Error).toBe(true);
expect(error.code).toBe(Parse.Error.INTERNAL_SERVER_ERROR);
expect(error.message).toBe('Database error');
}
});
it('should transform TransientTransactionError to Parse.Error.INTERNAL_SERVER_ERROR', async () => {
const adapter = new MongoStorageAdapter({ uri: databaseURI });
await adapter.connect();
const mockError = new Error('Transient transaction error');
mockError.hasErrorLabel = label => label === 'TransientTransactionError';
try {
adapter.handleError(mockError);
fail('Expected handleError to throw');
} catch (error) {
expect(error instanceof Parse.Error).toBe(true);
expect(error.code).toBe(Parse.Error.INTERNAL_SERVER_ERROR);
expect(error.message).toBe('Database error');
}
});
it('should not transform non-transient errors', async () => {
const adapter = new MongoStorageAdapter({ uri: databaseURI });
await adapter.connect();
const mockError = new Error('Some other error');
mockError.name = 'SomeOtherError';
try {
adapter.handleError(mockError);
fail('Expected handleError to throw');
} catch (error) {
expect(error instanceof Parse.Error).toBe(false);
expect(error.message).toBe('Some other error');
}
});
it('should handle null/undefined errors', async () => {
const adapter = new MongoStorageAdapter({ uri: databaseURI });
await adapter.connect();
try {
adapter.handleError(null);
fail('Expected handleError to throw');
} catch (error) {
expect(error).toBeNull();
}
try {
adapter.handleError(undefined);
fail('Expected handleError to throw');
} catch (error) {
expect(error).toBeUndefined();
}
});
});
describe('MongoDB Client Metadata', () => {
it('should not pass metadata to MongoClient by default', async () => {
const adapter = new MongoStorageAdapter({ uri: databaseURI });

View File

@@ -55,7 +55,7 @@ describe('Server Url Checks', () => {
parseServerProcess.on('close', async code => {
expect(code).toEqual(1);
expect(stdout).not.toContain('UnhandledPromiseRejectionWarning');
expect(stderr).toContain('MongoServerSelectionError');
expect(stderr).toContain('Database error');
await reconfigureServer();
done();
});

View File

@@ -73,7 +73,7 @@ describe('server', () => {
}),
});
const error = await server.start().catch(e => e);
expect(`${error}`.includes('MongoServerSelectionError')).toBeTrue();
expect(`${error}`.includes('Database error')).toBeTrue();
await reconfigureServer();
});

View File

@@ -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;
}

View File

@@ -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'));
}
};