#19887: fix: allow node role to call health RPC
gateway
size: XS
Cluster:
Security Enhancements and Fixes
## Summary
- The companion app (build 12195) sends `health` RPCs on its node-role WebSocket connection
- `authorizeGatewayMethod()` in `src/gateway/server-methods.ts` rejects all methods not in `NODE_ROLE_METHODS` for the node role
- Since `health` is in `READ_METHODS` (operator-only), node connections get an instant `INVALID_REQUEST` rejection
- The companion app retries aggressively on failure, creating a tight loop that drives both the gateway and companion app to 100%+ CPU
The fix adds a single check before the blanket node rejection to allow `health` through for the node role:
```ts
if (role === "node" && method === "health") {
return null;
}
```
## Test plan
- [ ] Start gateway with a companion app connected as both operator and node roles
- [ ] Verify node-role connection health checks return success instead of `unauthorized role: node`
- [ ] Verify operator-role connection health checks still work
- [ ] Verify gateway and companion app CPU usage stays low (was 100%+ before fix)
- [ ] Verify other node-role restrictions are still enforced (non-health methods still rejected)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Fixes a CPU spike caused by the companion app's node-role WebSocket connection being rejected when calling the `health` RPC. The `authorizeGatewayMethod()` function in `server-methods.ts` rejected all methods not in `NODE_ROLE_METHODS` for the node role, but the companion app sends `health` RPCs on this connection. The rejected requests triggered aggressive retries, creating a tight loop that drove CPU to 100%+.
The fix adds a targeted exception for the `health` method before the blanket node-role rejection, returning `null` (authorized) instead of an error. The `health` handler itself has no operator-specific logic, so this is safe.
- The fix is minimal (3 lines) and correctly placed in the authorization flow between the `NODE_ROLE_METHODS` allowlist and the node rejection gate
- The existing e2e test in `server.roles-allowlist-update.e2e.test.ts` verifies that other methods (e.g. `status`) remain rejected for node roles, but no automated test covers the new `health` exception for node role specifically
<h3>Confidence Score: 4/5</h3>
- This PR is safe to merge — it adds a minimal, well-scoped authorization exception for a read-only endpoint.
- The change is a 3-line, narrowly-scoped fix that only affects the `health` method for `node` role connections. The `health` handler has no operator-specific logic, so granting node access is safe. The authorization flow for all other methods and roles is unchanged. The only reason this isn't a 5 is the absence of an automated test for this specific authorization path.
- No files require special attention
<sub>Last reviewed commit: f624845</sub>
<!-- greptile_other_comments_section -->
<sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#21529: Gateway: allow node health and throttle repeated unauthorized role ...
by doomsday616 · 2026-02-20
84.7%
#12802: fix(gateway): default unscoped operator connections to read-only
by yubrew · 2026-02-09
75.9%
#6846: fix: bridge node.pair.* tools to device pairing store
by cortexuvula · 2026-02-02
75.4%
#19437: Gateway: respect custom bind host for local health/RPC target resol...
by frudas24 · 2026-02-17
73.8%
#23690: fix(gateway): subagent sessions fail with pairing required on loopb...
by yinghaosang · 2026-02-22
73.7%
#17753: fix: Control UI unusable over HTTP - missing scopes
by MisterGuy420 · 2026-02-16
73.4%
#22341: fix(status): detect node-only mode and show remote gateway info
by therk · 2026-02-21
73.4%
#17605: fix: preserve scopes when disableControlUiDeviceAuth is enabled
by MisterGuy420 · 2026-02-16
73.3%
#19885: test(gateway,browser): isolate tests from ambient OPENCLAW_GATEWAY_...
by NewdlDewdl · 2026-02-18
72.9%
#22109: fix(gateway): allow Control UI session patch/delete
by lc708 · 2026-02-20
72.8%