← Back to PRs

#22838: fix(gateway): auto-approve loopback pairing for scope/role upgrades

by GodsBoy open 2026-02-21 18:49 View on GitHub →
gateway size: XS
## Summary - Auto-approve **all** device pairing requests from loopback connections, not just initial pairing. This fixes internal gateway calls (`sessions_spawn`, cron jobs, browser control) that connect via loopback with varying least-privilege scopes and were incorrectly rejected with `1008 pairing required` on scope/role upgrades. ## Root Cause `callGateway` creates a new WebSocket connection per RPC call, each with a single least-privilege scope (e.g. `operator.admin` for `sessions.patch`, `operator.write` for `agent`). The device identity is persistent, so the first call pairs the device with one scope set. Subsequent calls with different scopes trigger a scope-upgrade pairing request. The `silent` flag (which enables auto-approve) was only set for `isLocalClient && reason === "not-paired"`, meaning scope/role upgrades on loopback were **not** auto-approved — even though the initial pairing was. This inconsistency caused all internal gateway calls to fail when their scopes differed from the initially paired set. ## Changes - `message-handler.ts`: Change `silent: isLocalClient && reason === "not-paired"` → `silent: isLocalClient` so all loopback pairing requests (initial, role-upgrade, scope-upgrade) are auto-approved. - `server.auth.e2e.test.ts`: Update test to verify scope upgrades are auto-approved on loopback (previously tested that they were rejected). ## Security The existing `isLocalClient` check (`isLocalDirectRequest`) already validates the connection is a genuine loopback connection (127.0.0.1/::1, local host header, no untrusted proxy headers). Initial device pairing was already auto-approved for local connections — this extends the same trust to scope/role upgrades, which is consistent with the security model: local machine access implies full gateway trust. Non-local connections (remote, proxied) are unaffected and still require manual pairing approval for scope/role upgrades. ## Test plan - [ ] Verify `auto-approves scope upgrades on loopback connections` test passes - [ ] Verify `single approval captures pending node and operator roles for the same device` test (non-local) still requires manual approval - [ ] Verify `sessions_spawn` subagent calls succeed without pairing prompts - [ ] Verify cron jobs with `sessionTarget: isolated` no longer fail with scope-upgrade pairing Fixes #21445, #22298 Relates to #12210

Most Similar PRs