fix(gateway): skip device pairing for local backend self-connections#30801
fix(gateway): skip device pairing for local backend self-connections#30801vincentkoc merged 4 commits intoopenclaw:mainfrom
Conversation
🔒 Aisle Security Analysis✅ We scanned this PR and did not find any security vulnerabilities. Aisle supplements but does not replace security review. Analyzed PR: #30801 at commit |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7575cfa66a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Greptile SummaryThis PR includes two separate fixes that should ideally be in separate PRs: Gateway Fix (matches PR title): Adds logic to skip device pairing for backend self-connections when the gateway connects to itself. The bypass is gated on three conditions: client ID is Cron Fix (not mentioned in PR description): Addresses a croner library bug where Both fixes are functionally correct, but mixing unrelated changes in a single PR makes review and git history harder to follow. Confidence Score: 4/5
Last reviewed commit: 7575cfa |
When gateway.tls is enabled, sessions_spawn (and other internal callGateway operations) creates a new WebSocket to the gateway. The gateway treated this self-connection like any external client and enforced device pairing, rejecting it with "pairing required" (close code 1008). This made sub-agent spawning impossible when TLS was enabled in Docker with bind: "lan". Skip pairing for connections that are gateway-client self-connections from localhost with valid shared auth (token/password). These are internal backend calls (e.g. sessions_spawn, subagent-announce) that already have valid credentials and connect from the same host. Closes openclaw#30740
7575cfa to
b069d0f
Compare
|
@aisle-research-bot review |
🔒 Aisle Security Analysis✅ We scanned this PR and did not find any security vulnerabilities. Aisle supplements but does not replace security review. Analyzed PR: #30801 at commit Last updated on: 2026-03-02T05:42:50Z |
…penclaw#30801) * fix(gateway): skip device pairing for local backend self-connections When gateway.tls is enabled, sessions_spawn (and other internal callGateway operations) creates a new WebSocket to the gateway. The gateway treated this self-connection like any external client and enforced device pairing, rejecting it with "pairing required" (close code 1008). This made sub-agent spawning impossible when TLS was enabled in Docker with bind: "lan". Skip pairing for connections that are gateway-client self-connections from localhost with valid shared auth (token/password). These are internal backend calls (e.g. sessions_spawn, subagent-announce) that already have valid credentials and connect from the same host. Closes openclaw#30740 * gateway: tighten backend self-pair bypass guard * tests: cover backend self-pairing local-vs-remote auth path * changelog: add gateway tls pairing fix credit --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#30801) * fix(gateway): skip device pairing for local backend self-connections When gateway.tls is enabled, sessions_spawn (and other internal callGateway operations) creates a new WebSocket to the gateway. The gateway treated this self-connection like any external client and enforced device pairing, rejecting it with "pairing required" (close code 1008). This made sub-agent spawning impossible when TLS was enabled in Docker with bind: "lan". Skip pairing for connections that are gateway-client self-connections from localhost with valid shared auth (token/password). These are internal backend calls (e.g. sessions_spawn, subagent-announce) that already have valid credentials and connect from the same host. Closes openclaw#30740 * gateway: tighten backend self-pair bypass guard * tests: cover backend self-pairing local-vs-remote auth path * changelog: add gateway tls pairing fix credit --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#30801) * fix(gateway): skip device pairing for local backend self-connections When gateway.tls is enabled, sessions_spawn (and other internal callGateway operations) creates a new WebSocket to the gateway. The gateway treated this self-connection like any external client and enforced device pairing, rejecting it with "pairing required" (close code 1008). This made sub-agent spawning impossible when TLS was enabled in Docker with bind: "lan". Skip pairing for connections that are gateway-client self-connections from localhost with valid shared auth (token/password). These are internal backend calls (e.g. sessions_spawn, subagent-announce) that already have valid credentials and connect from the same host. Closes openclaw#30740 * gateway: tighten backend self-pair bypass guard * tests: cover backend self-pairing local-vs-remote auth path * changelog: add gateway tls pairing fix credit --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#30801) * fix(gateway): skip device pairing for local backend self-connections When gateway.tls is enabled, sessions_spawn (and other internal callGateway operations) creates a new WebSocket to the gateway. The gateway treated this self-connection like any external client and enforced device pairing, rejecting it with "pairing required" (close code 1008). This made sub-agent spawning impossible when TLS was enabled in Docker with bind: "lan". Skip pairing for connections that are gateway-client self-connections from localhost with valid shared auth (token/password). These are internal backend calls (e.g. sessions_spawn, subagent-announce) that already have valid credentials and connect from the same host. Closes openclaw#30740 * gateway: tighten backend self-pair bypass guard * tests: cover backend self-pairing local-vs-remote auth path * changelog: add gateway tls pairing fix credit --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#30801) * fix(gateway): skip device pairing for local backend self-connections When gateway.tls is enabled, sessions_spawn (and other internal callGateway operations) creates a new WebSocket to the gateway. The gateway treated this self-connection like any external client and enforced device pairing, rejecting it with "pairing required" (close code 1008). This made sub-agent spawning impossible when TLS was enabled in Docker with bind: "lan". Skip pairing for connections that are gateway-client self-connections from localhost with valid shared auth (token/password). These are internal backend calls (e.g. sessions_spawn, subagent-announce) that already have valid credentials and connect from the same host. Closes openclaw#30740 * gateway: tighten backend self-pair bypass guard * tests: cover backend self-pairing local-vs-remote auth path * changelog: add gateway tls pairing fix credit --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#30801) * fix(gateway): skip device pairing for local backend self-connections When gateway.tls is enabled, sessions_spawn (and other internal callGateway operations) creates a new WebSocket to the gateway. The gateway treated this self-connection like any external client and enforced device pairing, rejecting it with "pairing required" (close code 1008). This made sub-agent spawning impossible when TLS was enabled in Docker with bind: "lan". Skip pairing for connections that are gateway-client self-connections from localhost with valid shared auth (token/password). These are internal backend calls (e.g. sessions_spawn, subagent-announce) that already have valid credentials and connect from the same host. Closes openclaw#30740 * gateway: tighten backend self-pair bypass guard * tests: cover backend self-pairing local-vs-remote auth path * changelog: add gateway tls pairing fix credit --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#30801) * fix(gateway): skip device pairing for local backend self-connections When gateway.tls is enabled, sessions_spawn (and other internal callGateway operations) creates a new WebSocket to the gateway. The gateway treated this self-connection like any external client and enforced device pairing, rejecting it with "pairing required" (close code 1008). This made sub-agent spawning impossible when TLS was enabled in Docker with bind: "lan". Skip pairing for connections that are gateway-client self-connections from localhost with valid shared auth (token/password). These are internal backend calls (e.g. sessions_spawn, subagent-announce) that already have valid credentials and connect from the same host. Closes openclaw#30740 * gateway: tighten backend self-pair bypass guard * tests: cover backend self-pairing local-vs-remote auth path * changelog: add gateway tls pairing fix credit --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#30801) * fix(gateway): skip device pairing for local backend self-connections When gateway.tls is enabled, sessions_spawn (and other internal callGateway operations) creates a new WebSocket to the gateway. The gateway treated this self-connection like any external client and enforced device pairing, rejecting it with "pairing required" (close code 1008). This made sub-agent spawning impossible when TLS was enabled in Docker with bind: "lan". Skip pairing for connections that are gateway-client self-connections from localhost with valid shared auth (token/password). These are internal backend calls (e.g. sessions_spawn, subagent-announce) that already have valid credentials and connect from the same host. Closes openclaw#30740 * gateway: tighten backend self-pair bypass guard * tests: cover backend self-pairing local-vs-remote auth path * changelog: add gateway tls pairing fix credit --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org> (cherry picked from commit e1e715c)
Summary
gateway.tls.enabled=true(withautoGenerate: true),sessions_spawnand other internalcallGatewayoperations fail with "pairing required" (WebSocket close code 1008). The gateway treats its own internal self-connection like an external client and enforces device pairing.bind: "lan". Without TLS, spawn fails withSECURITY ERROR(ws:// to non-loopback). With TLS, spawn fails withpairing required. Users have no workaround.src/gateway/server/ws-connection/message-handler.ts— detect backend self-connections (gateway-client from localhost with valid shared auth) and skip pairing for them.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
sessions_spawnnow works whengateway.tls.enabled=truewithautoGenerate: truebind: "lan"+ TLSSecurity Impact (required)
NoNo— only skips pairing for connections that already passed shared authNoNoNoThe pairing bypass is gated on three conditions: (1) client ID is
gateway-client, (2) shared auth (token/password) succeeded, and (3) connection is from localhost. External clients still require pairing.Repro + Verification
Environment
Steps
tls: { enabled: true, autoGenerate: true }andbind: "lan"sessions_spawnfrom within a sessionExpected
wss://127.0.0.1:portand completes handshakeActual
1008: pairing requiredEvidence
Human Verification (required)
Compatibility / Migration
YesNoNoFailure Recovery (if this breaks)
isBackendSelfConnectioncheck and revertskipPairinglogicsrc/gateway/server/ws-connection/message-handler.tsRisks and Mitigations
Risk: A malicious process on the same host could impersonate
gateway-clientand skip pairing.Mitigation: The bypass requires valid shared auth (token/password) AND localhost origin. An attacker with the token from the same host already has full gateway access.