feat: token-auth removal, security hardening, Stripe-style compat layer (v0.9.2)
Testing / test (push) Successful in 41s
Package Extension / package-extension (push) Successful in 35s
Build & Publish Package / publish (push) Successful in 46s

- Remove token auth entirely; only Ed25519 pubkey auth or --no-auth
- Add 32 MB message-size cap in serve and client (DoS protection)
- Set Unix socket to 0o600 after bind in native_host (multi-user hardening)
- Enforce browser-cli/VERSION user-agent on all TCP connections
- Add PROTOCOL_MIN_CLIENT check (>= 0.9.0) server- and client-side
- Include server_version + min_client_version in challenge frame
- Add browser_cli/version_manager.py: parse_version, get_installed_version
- Add browser_cli/compat.py: Stripe-style versioning layer with adapt_request
  / adapt_response hooks; baseline 0.9.2, no shims needed yet
- Fix BrowserCLI key handling: no Path() wrap for agent specs
- Fix _multi_browser_targets() to forward key to remote_browser_targets()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-02 21:59:46 +02:00
parent b98c4ae116
commit c1a5ef9dd7
17 changed files with 267 additions and 237 deletions
+4 -4
View File
@@ -16,10 +16,10 @@ def _handle(command, args=None, profile=None):
raise SystemExit(1)
def _handle_multi(command, args=None, profile=None, remote=None, token=None):
def _handle_multi(command, args=None, profile=None, remote=None):
try:
if remote:
return send_command(command, args or {}, profile=profile, remote=remote, token=token)
return send_command(command, args or {}, profile=profile, remote=remote)
return send_command(command, args or {}, profile=profile)
except (BrowserNotConnected, RuntimeError):
return None
@@ -32,7 +32,7 @@ def _multi_browser_targets():
remote = root.obj.get("remote")
key = root.obj.get("key")
if remote:
targets = remote_browser_targets(remote, root.obj.get("token"), key=key)
targets = remote_browser_targets(remote, key=key)
else:
targets = active_browser_targets(key=key)
if len(targets) <= 1 and not any(target.remote for target in targets):
@@ -99,7 +99,7 @@ def session_list():
if targets:
sessions = []
for target in targets:
result = _handle_multi("session.list", profile=target.profile, remote=target.remote, token=target.token)
result = _handle_multi("session.list", profile=target.profile, remote=target.remote)
if result is None:
continue
sessions.extend({**session, "browser": target.display_name} for session in result)