My local relay (127.0.0.1:8765) proxies Chrome DevTools Protocol commands to a headless browser whose cookie jar holds my logged-in sessions. A shared secret in a header was never enough: any web page I visit can fire fetch at loopback. Same-origin policy stops the response from being read, but the request still reaches the server, and a preflight is a request too. So the relay had to answer one question on every call: which extension is actually talking to me?
Last week suleyman416 opened PR #1 on the Lightpanda Session Bridge with exactly that hardening. I merged it on the 9th after running the tests locally. Here is what landed and the one subtlety that made it interesting.
The mechanism
The caller's Origin header looks like chrome-extension://<id>/.... The ID is 32 characters from the alphabet a-p (it is derived from the extension's public key). Validation is a regex fullmatch, not a prefix check:
EXTENSION_ID_RE = re.compile(r"^[a-p]{32}$")
OFFICIAL_EXTENSION_ID = "fcigkjkchglchhohedljlenopbkgnino"
The relay keeps a pinned ID, checked on every token-delivering or CDP-executing path (/v1/bootstrap, /v1/sessions, /v1/cdp) plus CORS preflights. Default policy: pin the official published ID. If your origin does not match, you get a 403 and the endpoint never runs.
The trap: unpacked extensions have path-derived IDs
During development you load the extension unpacked (chrome://extensions -> Load unpacked), and Chrome derives the extension ID from a hash of the installation path, not a public key. Every checkout on every machine gets a different ID. A strict default pin would have broken the exact people the project needs: anyone running a custom build.
The PR solved it with three explicit modes instead of one clever guess:
- Default: official ID pinned. Safest for users installing the packaged extension.
-
TOFU (
LP_BRIDGE_TOFU=1): first caller pins its ID to~/.config/lightpanda-bridge/pinned_extension_id(written0600), everyone else is then checked against it. Trust on first use, like SSH known_hosts. -
Allowlist (
LP_BRIDGE_ALLOWED_EXTENSION_IDS): comma-separated IDs for CI or multi-machine setups.
What TOFU costs you
Trust on first use trusts the first caller. If anything can race your extension to the relay on a cold start, it pins the attacker's ID and you never notice. That is why TOFU is opt-in and off by default: the failure mode is quiet, and quiet failure modes should require an environment variable, not a code path.
The practical lesson I take from this PR: when you secure a loopback service, "who is allowed to call me" cannot be answered by the absence of an Origin (that is how curl looks) nor by a token alone (tokens leak into logs and shell history). Bind the secret and the identity together, make the strict mode the default, and make the permissive mode loud.
The relay is ~1,200 lines of Python and the whole pinning layer is under 100. If you run an agent with a CDP endpoint on localhost, this is a cheap afternoon of work.",
Top comments (0)