Session Forking: How Slack Detects Stolen Cookies

Cookies are the cornerstone of session management on the web. For Slack, each time a user authenticates with a workspace, a session cookie is updated to reflect that state change. Because session cookies uniquely identify users, they are prime targets for malware that silently exfiltrates sensitive data from compromised devices. When attackers replay stolen cookies, they can impersonate legitimate users across applications, including Slack workspaces that often hold confidential business communications.

Admins can limit exposure using Slack's session duration feature, which forces re-authentication after a configurable period. This is analogous to regularly changing the locks on your house: a copied key becomes useless after the lock is replaced. However, this approach has limitations—users find overly short sessions disruptive, and duration alone doesn't reveal when an attacker is actively using a stolen credential. To close this gap, Slack's engineering team built a detection system that identifies when a session cookie is being used from more than one device simultaneously, a pattern they call session forking.

The Core Signal: Last Access Timestamp

The primary mechanism for detecting session forking is the last access timestamp, which records when the server last set the cookie on the client. This value is stored both in the cookie itself and in Slack's database. On every subsequent request, the server compares the timestamp embedded in the incoming cookie against the value stored in the database. A mismatch indicates that the client is presenting an outdated version of the cookie—strong evidence that the session has been forked.

Diagram showing a cookie being stolen by an attacker

Under normal operation, the server periodically refreshes the cookie with a newer last access timestamp and syncs the database value. When a malicious actor steals a cookie, they typically obtain an older copy. If they attempt to use it, the server detects the timestamp mismatch. Conversely, if an attacker engages with Slack regularly using a stolen cookie, their actions update the timestamp for that copy. When the original user returns with their older cached cookie, the comparison against the fresher database value reveals the fork.

Diagram of a request that takes a session cookie, compares the timestamp with the value in the database, writes a new timestamp to the database, and returns a new session cookie to a client

The timestamp alone cannot distinguish which side of a forked session is legitimate; it only reveals that multiple copies exist when there should be one.

Refining Detection to Reduce Noise

Early testing of the detection logic produced both false negatives and false positives. Pilot customers, who planned to automatically invalidate sessions flagged as forked, required high detection reliability to avoid disrupting legitimate work. Investigation revealed several edge cases where normal user behavior triggered false alarms.

One significant cause was clients that failed to receive or store updated cookies, leaving the client-side timestamp permanently misaligned with the database. To address this, Slack introduced the IP address as a secondary signal. If the last access time differs but the request originates from the same IP stored with the old timestamp, the traffic is likely from the original device rather than a stolen cookie. This single change eliminated a substantial proportion of false positives.

Diagram showing a response containing a new session cookie failing to reach the client and a second request that triggers a detection event when the client presents the old cookie value to the server

The timestamp comparison approach relies on clients reliably storing new cookies. Failures occurred in cases such as laptops sleeping before the server response was received. To mitigate this, Slack implemented a two-phase update process where each step is idempotent. Instead of directly updating the session cookie, the server first sets a separate "session candidate" cookie. When the client presents this candidate on a subsequent request, the server promotes it to the session cookie and updates the database timestamp.

Diagram showing one request where a session candidate cookie is set after comparing the timestamp with the database and a second request compares the timestamp with both the session and session candidate cookies. That request promotes the value in the session candidate cookie to be the new value of the session cookie and unsets the session candidate cookie

This design naturally handles interrupted responses. If the server sets a session candidate cookie but never sees it echoed back, it simply sets it again. If the hop session candidate is received but the promotion headers are lost, those headers are re-sent. When the client provides both cookies, the server accepts either timestamp for comparison against the database value. This ensures the system resumes progress from wherever it left off, preventing false positives from transient network issues.

Diagram showing several requests where some of the responses do not reach the client. The system continues working, despite this

Race Condition Mitigation

Slack clients send bursts of API requests in rapid succession. To avoid false positives from in-flight requests that carry an older cookie version while the database has just been updated, the server ignores timestamp mismatches within a narrowly defined window after a database update. An attacker could theoretically exploit this window, but it would require predicting the exact moment the original user triggers a request that updates the database—a virtually impossible task given that any error outside the window immediately reveals the fork.

Risk Assessment and Operational Efficiency

Beyond the last access timestamp, Slack combines additional device and network signals to algorithmically classify detections as low, medium, or high risk. Only high-risk events are written to the audit log, which helps keep the signal meaningful for security teams. The algorithm continues to be refined to minimize false positives further.

Diagram showing several requests in short succession all comparing the timestamp before a final request sets a new timestamp and updates the cookie

Performance was also a key concern. Adding a database read on every API request would impose significant load, particularly given how chatty Slack's real-time clients can be. The solution exploits the fact that a fresh timestamp indicates the server recently set the cookie—meaning any fork would have already been detected at that point. As a result, the system skips database reads for cookies within the recent window, only interacting with the database after some time has passed. Since most Slack usage occurs in bursts, this approach keeps the vast majority of requests free of extra database load.

Rollout and Communication

As with other anomaly detection features, Slack worked closely with pilot customers to develop the understanding that anomalies are signals for investigation rather than definitive indicators of malicious behavior. Legitimate causes, such as a computer restored from a backup, can also produce forking events. The limited rollout period allowed Slack to refine the detection logic—including the two-phase cookie approach—and reduce noise before gradually deploying to the entire user base.

Detection events are delivered to customers through Slack's audit log, which can be ingested into external security event managers like Splunk or ELK for correlation with other data streams and informed security decisions.

Next Steps

The current system delivers detections to admins, who can investigate and respond. Looking ahead, Slack sees an opportunity to improve the system further by automatically invalidating sessions that receive a high-risk detection. This would sign out both the legitimate user and the attacker, forcing the former to re-authenticate while cutting off the latter's ongoing impersonation attempts.