Skip to content

Commit 63a6d21

Browse files
committed
fix: resolve merge conflict with upstream alpha
2 parents 0b42ba4 + 5a58583 commit 63a6d21

File tree

6 files changed

+70
-8
lines changed

6 files changed

+70
-8
lines changed

changelogs/CHANGELOG_alpha.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# [9.6.0-alpha.30](https://github.com/parse-community/parse-server/compare/9.6.0-alpha.29...9.6.0-alpha.30) (2026-03-16)
2+
3+
4+
### Bug Fixes
5+
6+
* Block dot-notation updates to authData sub-fields and harden login provider checks ([#10223](https://github.com/parse-community/parse-server/issues/10223)) ([12c24c6](https://github.com/parse-community/parse-server/commit/12c24c6c6c578219703aaea186625f8f36c0d020))
7+
18
# [9.6.0-alpha.29](https://github.com/parse-community/parse-server/compare/9.6.0-alpha.28...9.6.0-alpha.29) (2026-03-16)
29

310

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "parse-server",
3-
"version": "9.6.0-alpha.29",
3+
"version": "9.6.0-alpha.30",
44
"description": "An express module providing a Parse-compatible API server",
55
"main": "lib/index.js",
66
"repository": {

spec/vulnerabilities.spec.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3010,6 +3010,56 @@ describe('(GHSA-fjxm-vhvc-gcmj) LiveQuery Operator Type Confusion', () => {
30103010
});
30113011
});
30123012

3013+
describe('authData dot-notation injection and login crash', () => {
3014+
it('rejects dotted update key that targets authData sub-field', async () => {
3015+
const user = new Parse.User();
3016+
user.setUsername('dotuser');
3017+
user.setPassword('pass1234');
3018+
await user.signUp();
3019+
3020+
const res = await request({
3021+
method: 'PUT',
3022+
url: `http://localhost:8378/1/users/${user.id}`,
3023+
headers: {
3024+
'Content-Type': 'application/json',
3025+
'X-Parse-Application-Id': 'test',
3026+
'X-Parse-REST-API-Key': 'rest',
3027+
'X-Parse-Session-Token': user.getSessionToken(),
3028+
},
3029+
body: JSON.stringify({ 'authData.anonymous".id': 'injected' }),
3030+
}).catch(e => e);
3031+
expect(res.status).toBe(400);
3032+
});
3033+
3034+
it('login does not crash when stored authData has unknown provider', async () => {
3035+
const user = new Parse.User();
3036+
user.setUsername('dotuser2');
3037+
user.setPassword('pass1234');
3038+
await user.signUp();
3039+
await Parse.User.logOut();
3040+
3041+
// Inject unknown provider directly in database to simulate corrupted data
3042+
const config = Config.get('test');
3043+
await config.database.update(
3044+
'_User',
3045+
{ objectId: user.id },
3046+
{ authData: { unknown_provider: { id: 'bad' } } }
3047+
);
3048+
3049+
// Login should not crash with 500
3050+
const login = await request({
3051+
method: 'GET',
3052+
url: `http://localhost:8378/1/login?username=dotuser2&password=pass1234`,
3053+
headers: {
3054+
'X-Parse-Application-Id': 'test',
3055+
'X-Parse-REST-API-Key': 'rest',
3056+
},
3057+
}).catch(e => e);
3058+
expect(login.status).toBe(200);
3059+
expect(login.data.sessionToken).toBeDefined();
3060+
});
3061+
});
3062+
30133063
describe('challenge endpoint authData provider value validation', () => {
30143064
it('rejects challenge request with null provider value without 500', async () => {
30153065
const res = await request({

src/Auth.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -523,10 +523,15 @@ const checkIfUserHasProvidedConfiguredProvidersForLogin = (
523523
userAuthData = {},
524524
config
525525
) => {
526-
const savedUserProviders = Object.keys(userAuthData).map(provider => ({
527-
name: provider,
528-
adapter: config.authDataManager.getValidatorForProvider(provider).adapter,
529-
}));
526+
const savedUserProviders = Object.keys(userAuthData)
527+
.map(provider => {
528+
const validator = config.authDataManager.getValidatorForProvider(provider);
529+
if (!validator || !validator.adapter) {
530+
return null;
531+
}
532+
return { name: provider, adapter: validator.adapter };
533+
})
534+
.filter(Boolean);
530535

531536
const hasProvidedASoloProvider = savedUserProviders.some(
532537
provider =>

src/Controllers/DatabaseController.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ class DatabaseController {
603603
})
604604
.then(schema => {
605605
Object.keys(update).forEach(fieldName => {
606-
if (fieldName.match(/^authData\.([a-zA-Z0-9_]+)\.id$/)) {
606+
if (fieldName.match(/^authData\./)) {
607607
throw new Parse.Error(
608608
Parse.Error.INVALID_KEY_NAME,
609609
`Invalid field name for update: ${fieldName}`

0 commit comments

Comments
 (0)