{
  "id": 6719911,
  "title": "My safety guard was checked in 6 places. Nothing ever set it.",
  "url": "https://urgent.news/2026/09/11/my-safety-guard-was-checked-in-6-places-nothing-ever-set-it",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-09-11T06:43:45.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/achiya-automation/my-safety-guard-was-checked-in-6-places-nothing-ever-set-it-55cd"
  },
  "original_language": "en",
  "account": "In a recent incident, the safety guard of a Safari MCP server was checked in six different locations with no success. The user performed a scheduled run and encountered a failure that they were unable to resolve. Thirty-three seconds after the background daemon restarted, a browser tab was opened and a capability token was handed back. This token is crucial for subsequent commands, as it verifies the server's authorization to interact with that specific tab. However, just thirty-three seconds later, the server refused the next command, citing that the tab safety token was forged, stale, ambiguous, or invalid for the origin. This issue could not be rectified from the client side, as the token could not be rotated. Switching to the tab by index was also refused, as reopening the tab was not allowed within the current MCP session. Closing the tab was also prohibited, as ownership could no longer be proven. The user was left with an unusable tab, requiring the agent to reopen its work in a new location.\n\nThe user examined two possible hypotheses for the failure, but both were ruled out within the same session. One hypothesis suggested that a newer tab invalidates an older token, while the other proposed that minting a token and opening a second tab after the first would work fine. The third hypothesis involved switching tabs by index, which corrupts the next command. Switching by index with no token at all also resulted in a successful command. Interestingly, the timing of the failure was consistent – all issues occurred once the daemon had been up for a few minutes, and only tabs created during the restart window exhibited problems. The first tab creation in this window took 22 seconds, during which the extension's background worker was still cold-starting.\n\nThe underlying mechanism lies in the browser-session epoch, which is a random identifier tied to one continuous browser run. If the browser restarts, the epoch rotates, and outdated tokens are correctly rejected. The epoch resides in session storage, which serves as the authority. The code snippet responsible for reading the browser-session epoch is as follows:\n\n```javascript\nasync function _ensureBrowserSessionEpoch () {\nif (! _browserSessionStorageAvailable ) {\nthrow new Error (\nBrowser session storage is unavailable; refusing durable tab authority\n);\n}\nif (/ ^ [ a-f0-9 ]{36} $ / . test ( _browserSessionEpoch )) {\nreturn _browserSessionEpoch ;\n}\n// Otherwise read storage, or mint and persist a new epoch\n}\n```\n\nThe crucial part of this function is the if statement that checks for the browser-session epoch availability and validity. Once the worker resolves the epoch into memory, it never consults session storage again throughout its entire lifespan. The cached copy is treated as the truth, and the worker stamps new tokens with the old epoch, writing them to durable storage. This behavior persists even when the epoch rotates in storage while the worker is still alive, resulting in a dead token being issued.\n\nThe user initially considered two potential hypotheses, but both were deemed incorrect. The first hypothesis posited that a newer tab invalidates an older token, while the second hypothesis suggested that minting a token and opening a second tab would function correctly. However, the third hypothesis emerged as the most plausible explanation. The safety guard in place was designed to track a counter that would notice a change in the browser-session identity during an in-flight operation. This counter was compared at six different call sites across the three functions responsible for epoch management. Three of these six comparisons were successful, while the remaining three were ineffective.\n\nThe dead guards, as they were dubbed, were located inside _ensureBrowserSessionEpoch and lacked the second clause necessary to catch the epoch rotation at mint time. Instead, the rotation was detected at rehydration, long after the bad tokens had been issued. The issue lay in the fact that the counter was assigned only once, on line 2819, and never incremented. This oversight allowed the worker to continue using the old epoch for token generation, leading to the observed failure. Consequently, the failure only manifested during rehydration, when the worker attempted to filter stale tokens based on the outdated epoch.",
  "summary": "A user of my Safari MCP server — the user was me, from a scheduled run — hit a failure I could not talk my way out of. Right after the background daemon restarted, the server opened a browser tab and handed back a capability token for it. The token is how every later command proves it is allowed to touch that tab, because the whole point of the ownership system is that the server must never act…",
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}