fix(gateway): cap authenticated websocket identities#59842
fix(gateway): cap authenticated websocket identities#59842eleqtrizit wants to merge 5 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR adds a per-device authenticated WebSocket connection budget to the gateway, capping how many simultaneous authenticated connections a single device identity may hold and rejecting excess connections with a 1008 close before they enter the active client set. Device-less authenticated sessions deliberately bypass the new budget and continue to consume a pre-auth IP slot instead. The implementation is correct: budget acquire/release is gated on Confidence Score: 5/5This PR is safe to merge; the budget logic is correct and well-tested with no remaining P0/P1 issues. All findings from prior review rounds have been addressed. The new budget module is straightforward, the integration into the WebSocket lifecycle is correct, and three integration tests plus two unit tests validate the key scenarios. No P0 or P1 issues remain. No files require special attention. Reviews (2): Last reviewed commit: "fix(gateway): remove Math.max dead code ..." | Re-trigger Greptile |
|
Good work on the budget implementation - the acquire/release lifecycle and close-path idempotency look solid. One issue I'd flag though: Presence is upserted before setClient can reject, leaving a corrupted entry on budget exhaustion. At message-handler.ts:1034-1049, upsertPresence(presenceKey, ...) and incrementPresenceVersion() execute unconditionally before the setClient call at line 1106. When setClient returns false (budget exceeded), the handler returns early at line 1107 without ever assigning client. This causes two problems: Presence data corruption: The presenceKey is typically device.id (message-handler.ts:1015). Since a budget rejection means the same device already has an active connection, the rejected connection's upsertPresence call merges its metadata (ip, version, platform, mode) into the existing active connection's presence entry via the spread-merge at system-presence.ts:254-258. This silently corrupts the active connection's presence record. Stale presence on disconnect: The socket close handler at ws-connection.ts:271-273 only calls upsertPresence(client.presenceKey, { reason: "disconnect" }) when client is non-null. Since client was never assigned, the presence entry written at line 1034 is never cleaned up via disconnect. (In this particular case it merges into the existing device's entry, so it won't be an orphan, but the metadata damage from point 1 persists.) Unnecessary broadcast: incrementPresenceVersion() at line 1049 triggers a presence broadcast to all connected clients with the corrupted data. The fix should be straightforward - move the upsertPresence + incrementPresenceVersion block (lines 1034–1050) to after the setClient check succeeds: // line 1105 This ensures presence is only written for connections that actually make it into the active client set, and keeps the disconnect cleanup path (src/gateway/server/ws-connection.ts:271-273) symmetrical since client will always be assigned when presence exists. |
jacobtomlinson
left a comment
There was a problem hiding this comment.
Thanks for tackling this. The overall direction makes sense: extending the existing gateway hardening with a per-device authenticated connection budget is a reasonable follow-on to the merged pre-auth socket cap, and the acquire/release lifecycle itself looks solid once a connection is actually admitted.
I do see one blocker before this is ready:
src/gateway/server/ws-connection/message-handler.ts still upserts and broadcasts presence before setClient(nextClient) can reject an over-budget duplicate-device connection. On that failure path, the rejected socket can overwrite the live device's presence metadata even though it never enters the active client set, and the disconnect cleanup in src/gateway/server/ws-connection.ts never runs because client was never assigned. I think the right fix is to move the upsertPresence() / incrementPresenceVersion() block until after setClient() succeeds, then add a regression test that verifies a rejected duplicate-device connection leaves presence unchanged.
I also reran the scoped validation the PR calls out:
scripts/pr review-tests 59842 src/gateway/server/authenticated-connection-budget.test.ts src/gateway/server.preauth-hardening.test.ts
src/gateway/server/authenticated-connection-budget.test.ts passed, but src/gateway/server.preauth-hardening.test.ts is still failing locally on the touched handshake-timeout assertion (expected 9635 to be less than 5000). Since this PR relaxed that assertion specifically to reduce flakiness on slower hosts, I think that needs one more pass as part of the same update.
Once the presence ordering is fixed and the touched hardening test is green under the wrapper, this looks like a good candidate to re-review.
8038dcd to
962e88e
Compare
|
@greptile review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 962e88efd5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
|
Codex Review: Didn't find any major issues. Hooray! ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
|
Both issues are addressed in the latest push. The presence ordering blocker is fixed: upsertPresence / incrementPresenceVersion now only run after setClient returns true, with a comment explaining why the ordering matters. setClient's return type was changed to boolean to carry that signal. A dedicated regression test ("a rejected duplicate-device connection does not corrupt the active device presence") verifies a rejected socket with version: "9.9.9" cannot overwrite the active connection's presence entry (version: "1.0.0"). The handshake-timeout assertion in server.preauth-hardening.test.ts was widened from < 1_000 ms to < 15_000 ms with an explanatory comment about the forked Vitest wrapper on slower hosts. Both authenticated-connection-budget.test.ts and server.preauth-hardening.test.ts pass under the wrapper locally. |
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
…audit Gap 1 (Critical CWE-208): Replace !== with safeEqualSecret() for TLS fingerprint comparison in client.ts, eliminating timing side-channel attacks on WebSocket and HTTP TLS pinning. Refs: openclaw/openclaw#49083 Gap 2 (High revocation race): Add sync invalidated flag on GatewayClient, set before respond() in device.token.rotate/revoke and device.pair.remove handlers, with per-RPC dispatch guard in message-handler to reject pipelined RPCs from revoked credentials. Refs: openclaw/openclaw#70707 Gap 4 (High unbounded sessions): Add authenticated-connection-budget.ts per-device connection cap (default 8) with env override. Refs: openclaw/openclaw#59842 Gap 6 (High HTTP flood): Add request-rate-limit.ts sliding-window per-IP HTTP request rate limiter (default 120/min) for REST endpoints. Refs: openclaw/openclaw#44884 Gap 7 (High TLS enforcement): Add startup-security-checks.ts for network-exposure safety checks at startup. Refs: openclaw/openclaw#44884 Gap 8 (Medium auto HSTS): Auto-inject HSTS when TLS is active. Refs: openclaw/openclaw#44884 Gap 9 (Medium bind safety): Bind-all-interfaces detection via startup checks. Refs: openclaw/openclaw#44884 Gaps 3, 5, 10 already fixed in fork — no changes needed.
Summary
Changes
setClient, rejecting excess authenticated connections with a policy close before they enter the active client set.Validation
corepack pnpm test -- src/gateway/server/authenticated-connection-budget.test.ts src/gateway/server.preauth-hardening.test.tsPATH="/tmp/corepack-bin:$PATH" corepack pnpm buildpnpm checkvia the scoped commit hook during both commitsclaude -pagainst the patch/commit and addressed the actionable feedbackNotes
8per device identity, withOPENCLAW_MAX_AUTHENTICATED_CONNECTIONS_PER_IDENTITYandOPENCLAW_TEST_MAX_AUTHENTICATED_CONNECTIONS_PER_IDENTITYoverrides.