feat: token-auth removal, security hardening, Stripe-style compat layer (v0.9.2)
- 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:
@@ -0,0 +1,49 @@
|
||||
"""
|
||||
Stripe-style version compatibility layer for browser-cli serve.
|
||||
|
||||
When a behaviour-breaking change ships in a new server version, add one entry
|
||||
to _COMPAT below:
|
||||
|
||||
("X.Y.Z", request_fn, response_fn)
|
||||
|
||||
- ``request_fn(msg: dict) -> dict``
|
||||
Upgrade an incoming client message from a client older than X.Y.Z to the
|
||||
current format before forwarding it to the native host.
|
||||
- ``response_fn(resp: bytes, command: str) -> bytes``
|
||||
Downgrade a native-host response to the format a client older than X.Y.Z
|
||||
expects before sending it back.
|
||||
|
||||
Either function may be ``None`` when only one direction needs adapting.
|
||||
|
||||
Entries must stay in ascending version order. ``adapt_request`` walks forward
|
||||
(oldest change first); ``adapt_response`` walks backward (newest change first)
|
||||
so the transformations compose correctly.
|
||||
|
||||
Current baseline: 0.9.1 — no shims needed yet.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
from typing import Callable
|
||||
from browser_cli.version_manager import parse_version
|
||||
|
||||
_COMPAT: list[tuple[str, Callable[[dict], dict] | None, Callable[[bytes, str], bytes] | None]] = [
|
||||
# ("1.0.0", _req_1_0_0, _resp_1_0_0),
|
||||
]
|
||||
|
||||
|
||||
def adapt_request(msg: dict, client_version: str) -> dict:
|
||||
"""Upgrade a client message to the current server format."""
|
||||
cv = parse_version(client_version)
|
||||
for version, req_fn, _ in _COMPAT:
|
||||
if cv < parse_version(version) and req_fn is not None:
|
||||
msg = req_fn(msg)
|
||||
return msg
|
||||
|
||||
|
||||
def adapt_response(resp: bytes, command: str, client_version: str) -> bytes:
|
||||
"""Downgrade a server response to the format the client expects."""
|
||||
cv = parse_version(client_version)
|
||||
for version, _, resp_fn in reversed(_COMPAT):
|
||||
if cv < parse_version(version) and resp_fn is not None:
|
||||
resp = resp_fn(resp, command)
|
||||
return resp
|
||||
Reference in New Issue
Block a user