#22838: fix(gateway): auto-approve loopback pairing for scope/role upgrades
gateway
size: XS
Cluster:
Device Pairing and Gateway Fixes
## 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
#23708: fix(gateway): auto-approve scope upgrades for loopback clients
by widingmarcus-cyber · 2026-02-22
89.1%
#22365: fix(gateway): auto-approve loopback scope upgrades
by AIflow-Labs · 2026-02-21
88.2%
#17425: fix(gateway): auto-approve scope/role upgrades for already-paired d...
by sauerdaniel · 2026-02-15
83.4%
#22280: fix(gateway): silently auto-approve local paired-device scope upgrades
by abhishekp76 · 2026-02-21
82.8%
#23690: fix(gateway): subagent sessions fail with pairing required on loopb...
by yinghaosang · 2026-02-22
82.4%
#22587: fix(gateway): silently auto-approve local paired-device scope upgrades
by abhishekp76 · 2026-02-21
81.9%
#22712: fix(gateway): auto-approve all device pairing for localhost connect...
by NewdlDewdl · 2026-02-21
80.1%
#22253: fix: auto-approve local loopback pairing for role/scope upgrades
by cjpraia · 2026-02-20
79.2%
#21622: fix(gateway): include read/write in CLI default operator scopes
by zerone0x · 2026-02-20
77.6%
#22381: Security/Gateway: block cross-origin silent auto-pairing in auth mo...
by bmendonca3 · 2026-02-21
77.1%