Control UI connections authenticated via gateway.auth.mode=trusted-proxy were
still forced through device pairing because pairing bypass only considered
shared token/password auth (sharedAuthOk). In trusted-proxy deployments,
this produced persistent "pairing required" failures despite valid trusted
proxy headers.
Treat authenticated trusted-proxy control-ui connections as pairing-bypass
eligible and allow missing device identity in that mode.
Fixes#25293
Co-authored-by: Cursor <cursoragent@cursor.com>
In trusted-proxy mode, sharedAuthResult is null because hasSharedAuth
only triggers for token/password in connectParams.auth. But the primary
auth (authResult) already validated the trusted-proxy — the connection
came from a CIDR in trustedProxies with a valid userHeader. This IS
shared auth semantically (the proxy vouches for identity), so operator
connections should be able to skip device identity.
Without this fix, trusted-proxy operator connections are rejected with
"device identity required" because roleCanSkipDeviceIdentity() sees
sharedAuthOk=false.
(cherry picked from commit e87048a6a650d391e1eb5704546eb49fac5f0091)
* Config UI: add tag filters and complete schema help/labels
* Config UI: finalize tags/help polish and unblock test suite
* Protocol: regenerate Swift gateway models
* fix(gateway): allow localhost Control UI without device identity when allowInsecureAuth is set
* fix(gateway): pass isLocalClient to evaluateMissingDeviceIdentity
* test: add regression tests for localhost Control UI pairing
* fix(gateway): require pairing for legacy metadata upgrades
* test(gateway): fix legacy metadata e2e ws typing
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Fixes the pairing required regression from #21236 for legacy paired devices
created without roles/scopes metadata. Detects legacy paired metadata shape
and skips upgrade enforcement while backfilling metadata in place on reconnect.
Co-authored-by: Josh Avant <830519+joshavant@users.noreply.github.com>
Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com>
* feat(gateway): add auth rate-limiting & brute-force protection
Add a per-IP sliding-window rate limiter to Gateway authentication
endpoints (HTTP, WebSocket upgrade, and WS message-level auth).
When gateway.auth.rateLimit is configured, failed auth attempts are
tracked per client IP. Once the threshold is exceeded within the
sliding window, further attempts are blocked with HTTP 429 + Retry-After
until the lockout period expires. Loopback addresses are exempt by
default so local CLI sessions are never locked out.
The limiter is only created when explicitly configured (undefined
otherwise), keeping the feature fully opt-in and backward-compatible.
* fix(gateway): isolate auth rate-limit scopes and normalize 429 responses
---------
Co-authored-by: buerbaumer <buerbaumer@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>