Skip to content

Clear cached notifications on clearIdentity before the UI mounts (#225880) - #190

Merged
floooat merged 1 commit into
masterfrom
fix-225880-clear-identity-notification-cache
Oct 21, 2026
Merged

floooat merged 1 commit into
masterfrom
fix-225880-clear-identity-notification-cache

Conversation

@floooat

@floooat floooat commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Symptom

A site calls Gleap.clearIdentity() inline on its login page, so the call is queued in window.GleapActions. After logout, the previous identified contact's message preview bubble is shown to the now-anonymous visitor on that browser. This is a privacy issue: messages addressed to a named contact are shown to whoever opens the page next.

Root cause

  • clearSession() → GleapNotificationManager.clearAllNotifications(false), whose whole body, including saveToGleapCache('unread-notifications', []), sat behind if (!this.notificationContainer) return;.
  • Queued snippet actions run synchronously when the module evaluates (Gleap.js, "Check for unperformed Gleap actions"). injectNotificationUI() only runs after session ready → config → DOM ready. A queued clearIdentity() therefore always found no container, and the gleap-widget-unread-notifications cache survived.
  • injectNotificationUI() → reloadNotificationsFromCache() then replayed every cached notification younger than 1 h. That cache key is shared by every contact on the browser.

Fix

  1. clearAllNotifications() now always resets the in-memory list and the persisted cache. Only the DOM teardown and the cross-tab broadcast still need the container. The tab channel only starts in injectNotificationUI(), so the broadcast was a no-op before mount anyway.
  2. Defence in depth: showNotification() stamps cachedForGleapId on each notification, and reloadNotificationsFromCache() keeps only entries stamped with the current session's gleapId. A reload can no longer show one contact another contact's notifications, even when the identity changes without clearIdentity().

Rollout side effect: bubbles cached by older builds are unstamped. They are at most 1 h old and are dropped once on the first page load after the update. Unread state in the messenger is unaffected.

Verification

Unit tests (src/GleapNotificationManager.test.js, new block "notification cache vs identity (#225880)"):

  • Red before the fix: clearAllNotifications(false) clears the persisted cache before the UI is mounted, showNotification stamps the receiving gleapId…, reloadNotificationsFromCache drops notifications cached for another (or no) gleapId (3 failed / 24 passed).
  • Green after: the file passes 27/27, and the full npx jest passes 33 suites / 581 tests. Two existing reload fixtures were updated to carry the stamp.

Browser reproduction. A local page seeds the unread cache with a previous contact's notification (written unstamped, as a pre-fix build writes it), then loads the standard async snippet with Gleap.initialize(<test project>) and a queued Gleap.clearIdentity():

Build Bubbles rendered gleap-widget-unread-notifications after load
sdk.gleap.io/latest (19.3.5, before) PREVIOUS USER: Hi Jane, … shown to the new anonymous session unchanged (1 entry)
this branch (after) none (container mounted) []

Regression check (this branch): the same contact gets a notification via Gleap.showNotification, which caches it stamped with its gleapId. After a reload the bubble is shown again.

Gleap ticket #225880.

🤖 Generated with Claude Code

…5880)

clearAllNotifications() returned early while the notification container
did not exist yet, so a clearIdentity() queued in the async snippet (it
runs before injectNotificationUI) left the previous contact's
unread-notifications cache in place, and the reload replayed it to the
next anonymous visitor.

Clear state and cache regardless of the container (only the DOM work
needs it), and stamp cached notifications with the receiving gleapId so
a reload only shows a contact its own notifications.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@floooat
floooat merged commit 9d4c15d into master Oct 21, 2026
1 check passed
@floooat floooat mentioned this pull request Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants