New anonymous user session acts as if it's created with password
Description
Parse Server is an open source backend that can be deployed to any infrastructure that can run Node.js. Developers can use the REST API to signup users and also allow users to login anonymously. Prior to version 4.5.1, when an anonymous user is first signed up using REST, the server creates session incorrectly. Particularly, the authProvider field in _Session class under createdWith shows the user logged in creating a password. If a developer later depends on the createdWith field to provide a different level of access between a password user and anonymous user, the server incorrectly classified the session type as being created with a password. The server does not currently use createdWith to make decisions about internal functions, so if a developer is not using createdWith directly, they are not affected. The vulnerability only affects users who depend on createdWith by using it directly. The issue is patched in Parse Server version 4.5.1. As a workaround, do not use the createdWith Session field to make decisions if one allows anonymous login.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
parse-servernpm | < 4.5.2 | 4.5.2 |
Affected products
1- Range: < 4.5.1
Patches
1147bd9a3dc43Merge pull request from GHSA-23r4-5mxp-c7g5
3 files changed · +65 −52
CHANGELOG.md+6 −1 modified@@ -1,7 +1,12 @@ ## Parse Server Changelog ### master -[Full Changelog](https://github.com/parse-community/parse-server/compare/4.5.0...master) +[Full Changelog](https://github.com/parse-community/parse-server/compare/4.5.1...master) + +### 4.5.1 +[Full Changelog](https://github.com/parse-community/parse-server/compare/4.5.0...4.5.1) + +- SECURITY FIX: Fixes incorrect session property `authProvider: password` of anonymous users. When signing up an anonymous user, the session field `createdWith` indicates incorrectly that the session has been created using username and password with `authProvider: password`, instead of an anonymous sign-up with `authProvider: anonymous`. This fixes the issue by setting the correct `authProvider: anonymous` for future sign-ups of anonymous users. This fix does not fix incorrect `authProvider: password` for existing sessions of anonymous users. Consider this if your app logic depends on the `authProvider` field. (Corey Baker) [GHSA-23r4-5mxp-c7g5](https://github.com/parse-community/parse-server/security/advisories/GHSA-23r4-5mxp-c7g5) ### 4.5.0 [Full Changelog](https://github.com/parse-community/parse-server/compare/4.4.0...4.5.0)
spec/ParseUser.spec.js+55 −51 modified@@ -2374,59 +2374,63 @@ describe('Parse.User testing', () => { }); }); - it('user get session from token on signup', done => { - Promise.resolve() - .then(() => { - return Parse.User.signUp('finn', 'human', { foo: 'bar' }); - }) - .then(user => { - request({ - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-Session-Token': user.getSessionToken(), - 'X-Parse-REST-API-Key': 'rest', - }, - url: 'http://localhost:8378/1/sessions/me', - }).then(response => { - const b = response.data; - expect(typeof b.sessionToken).toEqual('string'); - expect(typeof b.createdWith).toEqual('object'); - expect(b.createdWith.action).toEqual('signup'); - expect(typeof b.user).toEqual('object'); - expect(b.user.objectId).toEqual(user.id); - done(); - }); - }); + it('user get session from token on signup', async () => { + const user = await Parse.User.signUp('finn', 'human', { foo: 'bar' }); + const response = await request({ + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-Session-Token': user.getSessionToken(), + 'X-Parse-REST-API-Key': 'rest', + }, + url: 'http://localhost:8378/1/sessions/me', + }); + const data = response.data; + expect(typeof data.sessionToken).toEqual('string'); + expect(typeof data.createdWith).toEqual('object'); + expect(data.createdWith.action).toEqual('signup'); + expect(data.createdWith.authProvider).toEqual('password'); + expect(typeof data.user).toEqual('object'); + expect(data.user.objectId).toEqual(user.id); }); - it('user get session from token on login', done => { - Promise.resolve() - .then(() => { - return Parse.User.signUp('finn', 'human', { foo: 'bar' }); - }) - .then(() => { - return Parse.User.logOut().then(() => { - return Parse.User.logIn('finn', 'human'); - }); - }) - .then(user => { - request({ - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-Session-Token': user.getSessionToken(), - 'X-Parse-REST-API-Key': 'rest', - }, - url: 'http://localhost:8378/1/sessions/me', - }).then(response => { - const b = response.data; - expect(typeof b.sessionToken).toEqual('string'); - expect(typeof b.createdWith).toEqual('object'); - expect(b.createdWith.action).toEqual('login'); - expect(typeof b.user).toEqual('object'); - expect(b.user.objectId).toEqual(user.id); - done(); - }); - }); + it('user get session from token on username/password login', async () => { + await Parse.User.signUp('finn', 'human', { foo: 'bar' }); + await Parse.User.logOut(); + const user = await Parse.User.logIn('finn', 'human'); + const response = await request({ + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-Session-Token': user.getSessionToken(), + 'X-Parse-REST-API-Key': 'rest', + }, + url: 'http://localhost:8378/1/sessions/me', + }); + const data = response.data; + expect(typeof data.sessionToken).toEqual('string'); + expect(typeof data.createdWith).toEqual('object'); + expect(data.createdWith.action).toEqual('login'); + expect(data.createdWith.authProvider).toEqual('password'); + expect(typeof data.user).toEqual('object'); + expect(data.user.objectId).toEqual(user.id); + }); + + it('user get session from token on anonymous login', async () => { + const user = await Parse.AnonymousUtils.logIn(); + const response = await request({ + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-Session-Token': user.getSessionToken(), + 'X-Parse-REST-API-Key': 'rest', + }, + url: 'http://localhost:8378/1/sessions/me', + }); + const data = response.data; + expect(typeof data.sessionToken).toEqual('string'); + expect(typeof data.createdWith).toEqual('object'); + expect(data.createdWith.action).toEqual('login'); + expect(data.createdWith.authProvider).toEqual('anonymous'); + expect(typeof data.user).toEqual('object'); + expect(data.user.objectId).toEqual(user.id); }); it('user update session with other field', done => {
src/RestWrite.js+4 −0 modified@@ -857,6 +857,10 @@ RestWrite.prototype.createSessionToken = async function () { return; } + if (this.storage['authProvider'] == null && this.data.authData) { + this.storage['authProvider'] = Object.keys(this.data.authData).join(','); + } + const { sessionData, createSession } = Auth.createSession(this.config, { userId: this.objectId(), createdWith: {
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-23r4-5mxp-c7g5ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2021-39138ghsaADVISORY
- github.com/parse-community/parse-server/commit/147bd9a3dc43391e92c36e05d5db860b04ca27dbghsax_refsource_MISCWEB
- github.com/parse-community/parse-server/releases/tag/4.5.1mitrex_refsource_MISC
- github.com/parse-community/parse-server/releases/tag/4.5.2ghsaWEB
- github.com/parse-community/parse-server/security/advisories/GHSA-23r4-5mxp-c7g5ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.