Skip to content

🐛 don't adopt another tab's session when it replaces ours directly#4537

Merged
BenoitZugmeyer merged 1 commit intov7from
benoit/fix-cross-tab-session-adoption
Apr 29, 2026
Merged

🐛 don't adopt another tab's session when it replaces ours directly#4537
BenoitZugmeyer merged 1 commit intov7from
benoit/fix-cross-tab-session-adoption

Conversation

@BenoitZugmeyer
Copy link
Copy Markdown
Member

Motivation

When a tab's session was replaced by another tab's session directly (ID-to-ID, without going through an intermediate expired state), the current tab would silently adopt the foreign session and start sending events under it — without any user interaction. Users on multi-tab setups could find their session data mixed across tabs unexpectedly.

Changes

  • Remove the !hasSession guard on sessionExpired = true so that a direct session ID replacement is treated the same as a normal expiry: this tab marks itself as expired and waits for a user interaction before starting a new session.

Test instructions

  1. Open the sandbox in two tabs. In tab 1, expire the session with DD_RUM.stopSession().
  2. In tab 2, simulate a new session by setting the cookie directly (e.g. via DevTools) to a new id=...&created=...&expire=... value.
  3. Interact with tab 1 — it should start its own fresh session, not adopt tab 2's session ID.

Checklist

  • Tested locally
  • Tested on staging
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.
  • Updated documentation and/or relevant AGENTS.md file

When another tab's session ID appeared in the cookie while this tab still
had an active session (direct ID-to-ID replacement, no intermediate
isExpired state), `sessionExpired` was never set to true because the
`!hasSession` guard only covered the normal expiry path. This let the
current tab immediately adopt the foreign session without waiting for a
user interaction.
@cit-pr-commenter-54b7da
Copy link
Copy Markdown

cit-pr-commenter-54b7da Bot commented Apr 28, 2026

Bundles Sizes Evolution

📦 Bundle Name Base Size Local Size 𝚫 𝚫% Status
Rum 168.82 KiB 168.82 KiB -5 B -0.00%
Rum Profiler 6.09 KiB 6.09 KiB 0 B 0.00%
Rum Recorder 21.25 KiB 21.25 KiB 0 B 0.00%
Logs 54.37 KiB 54.37 KiB -5 B -0.01%
Rum Slim 127.19 KiB 127.19 KiB -5 B -0.00%
Worker 22.99 KiB 22.99 KiB 0 B 0.00%
🚀 CPU Performance

Pending...

🧠 Memory Performance
Action Name Base Memory Consumption Local Memory Consumption 𝚫
addglobalcontext N/A 39.18 KiB N/A
addaction N/A 66.04 KiB N/A
addtiming N/A 38.97 KiB N/A
adderror N/A 71.62 KiB N/A
startstopsessionreplayrecording N/A 41.05 KiB N/A
startview N/A 475.23 KiB N/A
logmessage N/A 54.96 KiB N/A

🔗 RealWorld

@datadog-prod-us1-6
Copy link
Copy Markdown

datadog-prod-us1-6 Bot commented Apr 28, 2026

Tests

🎉 All green!

❄️ No new flaky tests detected
🧪 All tests passed

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 77.57% (-0.00%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 7da2b2b | Docs | Datadog PR Page | Give us feedback!

@BenoitZugmeyer BenoitZugmeyer marked this pull request as ready for review April 28, 2026 19:20
@BenoitZugmeyer BenoitZugmeyer requested a review from a team as a code owner April 28, 2026 19:20
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7da2b2b35f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (!hasSession) {
sessionExpired = true
}
sessionExpired = true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Regenerate before accepting replaced sessions on activity

When another tab directly replaces the cookie with an active different id, this marks the local manager expired and skips immediate adoption, but the shared store still contains newState.id. On the next user activity in this tab, throttledExpandOrRenew resets sessionExpired = false and expandOrRenew preserves that active id, so handleStateChange will add the other tab's session instead of creating this tab's fresh session. This means the scenario described by the change still mixes sessions as soon as the user interacts unless the replaced state is first expired/ignored in storage.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mixes sessions as soon as the user interacts unless the replaced state is first expired/ignored in storage.

This is the expected behavior

@BenoitZugmeyer BenoitZugmeyer merged commit 6810f11 into v7 Apr 29, 2026
20 checks passed
@BenoitZugmeyer BenoitZugmeyer deleted the benoit/fix-cross-tab-session-adoption branch April 29, 2026 08:00
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 29, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants