Skip to content

Commit

Permalink
Merge pull request from GHSA-7pr3-p5fm-8r9x
Browse files Browse the repository at this point in the history
* fix: strip sessionToken on _User LiveQuery

* delete authData

* add changelog

* Update package.json

* Update CHANGELOG.md

* add changes

* Update ParseLiveQuery.spec.js

Co-authored-by: Manuel <5673677+mtrezza@users.noreply.github.com>
  • Loading branch information
dblythy and mtrezza authored Sep 30, 2021
1 parent bcbc035 commit 834ae36
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 4 deletions.
11 changes: 9 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Jump directly to a version:

| 4.x |
|--------------------------------------|
| [**4.10.3 (latest release)**](#4103) |
| [**4.10.4 (latest release)**](#4104) |
| [4.10.3](#4103) |
| [4.10.2](#4102) |
| [4.10.1](#4101) |
| [4.10.0](#4100) |
Expand Down Expand Up @@ -94,7 +95,7 @@ Jump directly to a version:
___

## Unreleased (Master Branch)
[Full Changelog](https://github.com/parse-community/parse-server/compare/4.10.3...master)
[Full Changelog](https://github.com/parse-community/parse-server/compare/4.10.4...master)

### Breaking Changes
- Improved schema caching through database real-time hooks. Reduces DB queries, decreases Parse Query execution time and fixes a potential schema memory leak. If multiple Parse Server instances connect to the same DB (for example behind a load balancer), set the [Parse Server Option](https://parseplatform.org/parse-server/api/master/ParseServerOptions.html) `databaseOptions.enableSchemaHooks: true` to enable this feature and keep the schema in sync across all instances. Failing to do so will cause a schema change to not propagate to other instances and re-syncing will only happen when these instances restart. The options `enableSingleSchemaCache` and `schemaCacheTTL` have been removed. To use this feature with MongoDB, a replica set cluster with [change stream](https://docs.mongodb.com/manual/changeStreams/#availability) support is required. (Diamond Lewis, SebC) [#7214](https://github.com/parse-community/parse-server/issues/7214)
Expand Down Expand Up @@ -156,6 +157,12 @@ ___
- Allow cloud string for ES modules (Daniel Blyth) [#7560](https://github.com/parse-community/parse-server/pull/7560)
- docs: Introduce deprecation ID for reference in comments and online search (Manuel Trezza) [#7562](https://github.com/parse-community/parse-server/pull/7562)

## 4.10.4
[Full Changelog](https://github.com/parse-community/parse-server/compare/4.10.3...4.10.4)

### Security Fixes
- Strip out sessionToken when LiveQuery is used on Parse.User (Daniel Blyth) [GHSA-7pr3-p5fm-8r9x](https://github.com/parse-community/parse-server/security/advisories/GHSA-7pr3-p5fm-8r9x)

## 4.10.3
[Full Changelog](https://github.com/parse-community/parse-server/compare/4.10.2...4.10.3)

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "parse-server",
"version": "4.10.3",
"version": "4.10.4",
"description": "An express module providing a Parse-compatible API server",
"main": "lib/index.js",
"repository": {
Expand Down
46 changes: 46 additions & 0 deletions spec/ParseLiveQuery.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,52 @@ describe('ParseLiveQuery', function () {
done();
});

it('should strip out session token in LiveQuery', async () => {
await reconfigureServer({
liveQuery: { classNames: ['_User'] },
startLiveQueryServer: true,
verbose: false,
silent: true,
});

const user = new Parse.User();
user.setUsername('username');
user.setPassword('password');
user.set('foo', 'bar');

const query = new Parse.Query(Parse.User);
query.equalTo('foo', 'bar');
const subscription = await query.subscribe();

const events = ['create', 'update', 'enter', 'leave', 'delete'];
const response = (obj, prev) => {
expect(obj.get('sessionToken')).toBeUndefined();
expect(obj.sessionToken).toBeUndefined();
expect(prev?.sessionToken).toBeUndefined();
if (prev && prev.get) {
expect(prev.get('sessionToken')).toBeUndefined();
}
};
const calls = {};
for (const key of events) {
calls[key] = response;
spyOn(calls, key).and.callThrough();
subscription.on(key, calls[key]);
}
await user.signUp();
user.unset('foo');
await user.save();
user.set('foo', 'bar');
await user.save();
user.set('yolo', 'bar');
await user.save();
await user.destroy();
await new Promise(resolve => process.nextTick(resolve));
for (const key of events) {
expect(calls[key]).toHaveBeenCalled();
}
});

afterEach(async function (done) {
const client = await Parse.CoreManager.getLiveQueryController().getDefaultLiveQueryClient();
client.close();
Expand Down
45 changes: 45 additions & 0 deletions spec/ParseUser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3966,6 +3966,51 @@ describe('Parse.User testing', () => {
ok(model._isLinked('facebook'), 'User should be linked to facebook');
});
});

it('should strip out authdata in LiveQuery', async () => {
const provider = getMockFacebookProvider();
Parse.User._registerAuthenticationProvider(provider);

await reconfigureServer({
liveQuery: { classNames: ['_User'] },
startLiveQueryServer: true,
verbose: false,
silent: true,
});

const query = new Parse.Query(Parse.User);
query.doesNotExist('foo');
const subscription = await query.subscribe();

const events = ['create', 'update', 'enter', 'leave', 'delete'];
const response = (obj, prev) => {
expect(obj.get('authData')).toBeUndefined();
expect(obj.authData).toBeUndefined();
expect(prev?.authData).toBeUndefined();
if (prev && prev.get) {
expect(prev.get('authData')).toBeUndefined();
}
};
const calls = {};
for (const key of events) {
calls[key] = response;
spyOn(calls, key).and.callThrough();
subscription.on(key, calls[key]);
}
const user = await Parse.User._logInWith('facebook');

user.set('foo', 'bar');
await user.save();
user.unset('foo');
await user.save();
user.set('yolo', 'bar');
await user.save();
await user.destroy();
await new Promise(resolve => process.nextTick(resolve));
for (const key of events) {
expect(calls[key]).toHaveBeenCalled();
}
});
});

describe('Security Advisory GHSA-8w3j-g983-8jh5', function () {
Expand Down
18 changes: 18 additions & 0 deletions src/LiveQuery/ParseLiveQueryServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,14 @@ class ParseLiveQueryServer {
deletedParseObject = res.object.toJSON();
deletedParseObject.className = className;
}
if (
(deletedParseObject.className === '_User' ||
deletedParseObject.className === '_Session') &&
!client.hasMasterKey
) {
delete deletedParseObject.sessionToken;
delete deletedParseObject.authData;
}
client.pushDelete(requestId, deletedParseObject);
} catch (error) {
Client.pushError(
Expand Down Expand Up @@ -337,6 +345,16 @@ class ParseLiveQueryServer {
originalParseObject = res.original.toJSON();
originalParseObject.className = res.original.className || className;
}
if (
(currentParseObject.className === '_User' ||
currentParseObject.className === '_Session') &&
!client.hasMasterKey
) {
delete currentParseObject.sessionToken;
delete originalParseObject?.sessionToken;
delete currentParseObject.authData;
delete originalParseObject?.authData;
}
const functionName = 'push' + res.event.charAt(0).toUpperCase() + res.event.slice(1);
if (client[functionName]) {
client[functionName](requestId, currentParseObject, originalParseObject);
Expand Down

0 comments on commit 834ae36

Please sign in to comment.