fix: [SDK-4818] resolve TOCTOU race on the current user - #1695
Merged
Conversation
…allbacks User executor network callbacks asked `isCurrentUser(...)` and then separately dereferenced `_user`. A concurrent login/logout landing between those two reads made the first answer stale, so a response could hydrate one user's properties and subscriptions onto another, clear a just-switched user's data, or log out a user the failed request had nothing to do with. Guard `_user` with a lock and add `currentUser(matching:)`, which reads it once and returns the instance only if it still owns the request's identity model. Callers use that returned instance instead of re-reading `_user`, so there is no window between the check and the mutation. The lock is not held across caller work, which fires model-store listeners into the operation repo and could deadlock; handing back the checked instance is what makes this safe. `clearUserData` now takes the user to clear for the same reason. Co-Authored-By: Cursor <cursoragent@cursor.com>
…ssor isCurrentUser answered "is this the current user?" from the identity model store while currentUser(matching:) answers it from the _user instance. The two disagree while a login or logout is in flight, which is the same split source of truth behind the TOCTOU race, so collapse every caller onto the accessor. Co-authored-by: Cursor <cursoragent@cursor.com>
sherwinski
reviewed
Jul 30, 2026
sherwinski
reviewed
Jul 30, 2026
…essor actually guarantees The docstring overclaimed that concurrent login/logout cannot apply one user's data to another; that holds for the returned instance's models, not the shared stores. Co-authored-by: Cursor <cursoragent@cursor.com>
sherwinski
approved these changes
Jul 31, 2026
Merged
This was referenced Aug 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
One Line Summary
Fix TOCTOU race where an
isCurrentUsercheck then a separate_usermutation can apply data to the wrong user after a concurrent login/logout.Details
Motivation
Executor callbacks checked whether a request belonged to the current user, then mutated
_userin a separate step. A concurrentlogin()/logout()between those steps could clear or hydrate the wrong user's data.Scope
_useraccess andcurrentUser(matching:)so the check and use share one read.isCurrentUserso "is this the current user?" has a single source of truth (_user).Testing
Unit testing
Manual testing
Not run here — unit coverage exercises the race window; please run
OneSignalUserTestslocally.Affected code checklist
Checklist
Overview
Testing
Final pass
Made with Cursor