Skip to content

fix(bridge): pin the loopback token exemption to the extension's stable origin - #110

Open
chintoleung wants to merge 1 commit into
omdsh-dev:mainfrom
chintoleung:fix/bridge-origin-pinning
Open

chintoleung wants to merge 1 commit into
omdsh-dev:mainfrom
chintoleung:fix/bridge-origin-pinning

Conversation

@chintoleung

Copy link
Copy Markdown
Contributor

Fixes #108

Problem

Any installed extension could bypass bearer-token auth by presenting its own chrome-extension:// Origin (prefix check in attach()).

Approach

  • The exemption is now an exact-match allowlist (trustedExtensionOrigins); default is the shipped extension's id. Chromium derives an unpacked extension's id from the manifest key, so this PR pins a committed key → stable id ampcoeplakeelcoengijbfbhjnlbdign across machines and updates. Unlisted origins — including other extensions — must present the token; origin trust never applies off loopback.
  • trustedExtensionOrigins entries are validated (chrome-extension://<32-char a-p id>) and the effective allowlist is logged at mount. [] is the explicit hardened mode (token pairing only) for hostile-extension or loopback-proxy (tailscale serve, ssh -L) topologies.
  • Migration: updating from pre-0.1.5 changes the extension id once (settings are stored per id) — READMEs and both installers now tell users to re-enter a configured remote bridge address/token. Version bumped to 0.1.5.
  • Drift guard: a test fails if the manifest key ever hashes to anything but the pinned id.

Boundary (documented)

The manifest key is public: the pin stops incidental cross-extension access, not deliberate key-cloning; origin checks bind browser contexts only. Hardened deployments set trustedExtensionOrigins: [] and pair the token.

Testing

  • New unit tests: unlisted-origin rejection, trusted-origin + non-loopback rejection, explicit [] fail-closed, invalid config entries throw, key→id drift guard.
  • e2e (real Chromium): asserts the loaded extension id is the pinned id and that a tokenless hello connects against the default allowlist; second case covers the paired-token path. Harness is now locale-independent and skips loudly.
  • Suites: bridge 160/160, extension 398/398, typecheck clean.

Notes for review

中文摘要

回环免 token 从「任意 chrome-extension:// 前缀」改为精确 Origin 白名单:扩展固定 manifest key,id 在各机器与升级间稳定,默认仅信任该 id;其余 Origin 一律携带 token。配置项含格式校验与启动日志,[] 为加固模式。0.1.5 前版本升级时 id 会变更一次,需重新填写远程桥地址/token(README 与安装器已注明)。

…le origin

Any installed extension could bypass bearer-token auth by presenting its
own chrome-extension:// Origin (prefix check). The exemption is now an
exact-match allowlist: the shipped extension pins a manifest key so its
Chromium id (ampcoeplakeelcoengijbfbhjnlbdign) is stable across machines
and updates, and that single origin is trusted by default. Every other
origin must present the token; origin trust never applies off loopback.

Hardening from adversarial review:
- trustedExtensionOrigins entries are validated (chrome-extension://<a-p
  32> only) and the effective allowlist is logged at mount; [] is the
  explicit hardened mode. A web-origin entry would have re-granted the
  trust this change removes.
- Docs state the real boundary: the manifest key is public, so the pin
  stops incidental cross-extension access, not deliberate key-cloning;
  hardened deployments pair the token. Loopback-terminating proxies
  (tailscale serve, ssh -L) documented.
- Updating from pre-0.1.5 changes the extension id once (settings are
  per id): READMEs and both installers now say to re-enter a configured
  remote bridge address/token. Extension version bumped to 0.1.5.
- Drift guard: a test fails if the manifest key ever hashes to anything
  but the pinned id; malformed keys are rejected, not munged.
- e2e now proves the pin: real Chromium must derive the pinned id and
  accept a tokenless hello against the default allowlist (plus the
  paired-token path), with a locale-independent harness and loud skips.
@chintoleung
chintoleung force-pushed the fix/bridge-origin-pinning branch from 6c60644 to a118d3a Compare October 5, 2026 08:25
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.

Bridge: any installed extension can connect without the token via a chrome-extension:// Origin

1 participant