parse-community / parse-community/parse-server
LiveQuery role cache is not invalidated for all users affected by a role write or delete
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 21.4k
- Forks
- 4.8k
- Avg merge
- 7h 45m
- Merged PRs (30d)
- 11
Description
New Issue Checklist
- Report security issues confidentially.
- Any contribution is under this license.
- Before posting search existing issues.
Issue Description
LiveQueryController.clearCachedRoles(user) invalidates the LiveQuery server's cached auth for a single user, and only when a user is present on the request. Both call sites pass the acting user:
src/RestWrite.js(runDatabaseOperation, role create and update)src/rest.js(del, role delete, added in #10620)
That leaves two cases where a role change does not invalidate LiveQuery's cached role closures:
- No user on the request.
clearCachedRolesreturns early whenuseris falsy, so a master key write or delete publishes nothing at all. Managing roles with the master key, from admin tooling or cloud code, is the common case. - Users other than the actor.
ParseCloudCodePublisher#onClearCachedRolespublishes a single{ userId }, andParseLiveQueryServer#_clearCachedRoles(userId)resolves_Sessionrows for that one user. Adding or removing a member, or deleting a role that other roles inherit from, changes the effective closure for users who are never signalled.
The blast radius is bounded, which is why this is filed separately rather than as a security report. The REST and auth side is already correct: cacheController.role.clear() is global and drops the cached closure for every user. ParseLiveQueryServer's authCache is an LRU bounded by cacheTimeout, so stale entries expire on their own. The gap is confined to LiveQuery event delivery being decided from a stale role closure until that TTL elapses.
This predates #10620 and applies equally to the role write path, which has behaved this way since #8026 introduced clearCachedRoles.
Steps to reproduce
- Start Parse Server with LiveQuery enabled for a class whose ACL grants read access to
role:Editors. - Log in as a user who is a member of
Editorsand subscribe to a query on that class. - Using the master key, delete the
Editorsrole (or remove the subscribed user from it). - Save an object matching the subscription.
Actual Outcome
The subscriber keeps receiving events for objects it can no longer read, until its authCache entry expires after cacheTimeout. With the master key, no clearCache message is published at all. With a session-authenticated request, only the acting user's sessions are invalidated, so other members of the role see the same staleness.
Expected Outcome
A role write or delete invalidates the LiveQuery auth cache for every session whose effective role closure changed, including when the request carries no user.
Environment
This is a code path report from review of #10620, not a runtime bug report, so the client and hosting fields are not meaningful.
Server
- Parse Server version:
9.10.1-alpha.6(present onalpha, and on every release since #8026) - Operating system:
n/a - Local or remote host:
n/a
Database
- System (MongoDB or Postgres):
n/a - Database version:
n/a - Local or remote host:
n/a
Client
- SDK (iOS, Android, JavaScript, PHP, Unity, etc):
n/a - SDK version:
n/a
Logs
None. The failure is silent by construction: clearCachedRoles returns early without logging when there is no user.
Notes on possible directions
Not a proposal, just the options that came up in review, both of which change the shape of the clearCache pub/sub message that is shared between LiveQuery server instances and therefore needs a back compat story for mixed-version deployments:
- Broadcast a clear-all when no specific user can be identified, accepting that it flushes every connection's auth cache on every role write.
- Publish the affected role id and let the LiveQuery server resolve the sessions to invalidate, which keeps the blast radius small but requires the server to expand the role closure.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the role write and delete call sites in src/RestWrite.js and src/rest.js, then read LiveQueryController.clearCachedRoles, ParseCloudCodePublisher#onClearCachedRoles, and ParseLiveQueryServer#_clearCachedRoles. Reproduce the master-key and non-acting-member cases from the issue. Done means affected sessions, including users reached through role membership or inheritance, stop receiving unauthorized events without breaking mixed-version clearCache messages.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- authentication, authorization, backend
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100