New Issue Checklist
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:
That leaves two cases where a role change does not invalidate LiveQuery's cached role closures:
- No user on the request.
clearCachedRoles returns early when user is 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#onClearCachedRoles publishes a single { userId }, and ParseLiveQueryServer#_clearCachedRoles(userId) resolves _Session rows 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
Editors and subscribe to a query on that class.
- Using the master key, delete the
Editors role (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
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.
New Issue Checklist
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 fix: Deleting a role does not invalidate the cached role closures #10620)That leaves two cases where a role change does not invalidate LiveQuery's cached role closures:
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.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'sauthCacheis an LRU bounded bycacheTimeout, 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
role:Editors.Editorsand subscribe to a query on that class.Editorsrole (or remove the subscribed user from it).Actual Outcome
The subscriber keeps receiving events for objects it can no longer read, until its
authCacheentry expires aftercacheTimeout. With the master key, noclearCachemessage 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
9.10.1-alpha.6(present onalpha, and on every release since fix: live query role cache does not clear when a user is added to a role #8026)n/an/aDatabase
n/an/an/aClient
n/an/aLogs
None. The failure is silent by construction:
clearCachedRolesreturns 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
clearCachepub/sub message that is shared between LiveQuery server instances and therefore needs a back compat story for mixed-version deployments: