From 17bde6e0417890c2fc1be1a45f1a6ef70dd2164a Mon Sep 17 00:00:00 2001 From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com> Date: Wed, 1 Apr 2026 21:00:34 +0100 Subject: [PATCH] fix: Session field guard bypass via falsy values for ACL and user fields --- spec/ParseSession.spec.js | 85 +++++++++++++++++++++++++++++++++++++++ src/RestWrite.js | 4 +- 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/spec/ParseSession.spec.js b/spec/ParseSession.spec.js index 9863a4f5bd..b622bb04c0 100644 --- a/spec/ParseSession.spec.js +++ b/spec/ParseSession.spec.js @@ -546,6 +546,91 @@ describe('Parse.Session', () => { expect(updateRes.data.code).toBe(Parse.Error.INVALID_KEY_NAME); }); + it('should reject null ACL when updating a session via PUT', async () => { + const user = await Parse.User.signUp('sessionupdatenull5', 'password'); + const sessionToken = user.getSessionToken(); + + const sessionRes = await request({ + method: 'GET', + url: 'http://localhost:8378/1/sessions/me', + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + 'X-Parse-Session-Token': sessionToken, + }, + }); + const sessionId = sessionRes.data.objectId; + + const updateRes = await request({ + method: 'PUT', + url: `http://localhost:8378/1/sessions/${sessionId}`, + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + 'X-Parse-Session-Token': sessionToken, + 'Content-Type': 'application/json', + }, + body: { + ACL: null, + }, + }).catch(e => e); + + expect(updateRes.data.code).toBe(Parse.Error.INVALID_KEY_NAME); + }); + + it('should reject null ACL when creating a session via POST', async () => { + const user = await Parse.User.signUp('sessioncreatenull1', 'password'); + const sessionToken = user.getSessionToken(); + + const createRes = await request({ + method: 'POST', + url: 'http://localhost:8378/1/sessions', + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + 'X-Parse-Session-Token': sessionToken, + 'Content-Type': 'application/json', + }, + body: { + ACL: null, + }, + }).catch(e => e); + + expect(createRes.data.code).toBe(Parse.Error.INVALID_KEY_NAME); + }); + + it('should reject null user when updating a session via PUT', async () => { + const user = await Parse.User.signUp('sessionupdatenull6', 'password'); + const sessionToken = user.getSessionToken(); + + const sessionRes = await request({ + method: 'GET', + url: 'http://localhost:8378/1/sessions/me', + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + 'X-Parse-Session-Token': sessionToken, + }, + }); + const sessionId = sessionRes.data.objectId; + + const updateRes = await request({ + method: 'PUT', + url: `http://localhost:8378/1/sessions/${sessionId}`, + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + 'X-Parse-Session-Token': sessionToken, + 'Content-Type': 'application/json', + }, + body: { + user: null, + }, + }).catch(e => e); + + expect(updateRes.data.code).toBe(Parse.Error.INVALID_KEY_NAME); + }); + describe('PUT /sessions/me', () => { it('should return error with invalid session token', async () => { const response = await request({ diff --git a/src/RestWrite.js b/src/RestWrite.js index 04b7ceccb3..c6c8db969c 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -1228,12 +1228,12 @@ RestWrite.prototype.handleSession = function () { } // TODO: Verify proper error to throw - if (this.data.ACL) { + if ('ACL' in this.data) { throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'Cannot set ' + 'ACL on a Session.'); } if (this.query) { - if (this.data.user && !this.auth.isMaster && this.data.user.objectId != this.auth.user.id) { + if ('user' in this.data && !this.auth.isMaster && this.data.user?.objectId !== this.auth.user.id) { throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'Invalid key name: user'); } else if ('installationId' in this.data) { throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'Invalid key name: installationId');