Basekick-Labs / Basekick-Labs/arc
Cluster auth hardening follow-ups: HMAC domain separation + don't forward client auth headers to peers
- Dominant language
- Go
- Stars
- 677
- Forks
- 53
- Avg merge
- 9h 14m
- Merged PRs (30d)
- 164
Description
Two pre-existing cluster-auth defense-in-depth items surfaced during the GHSA-p378-jp5r-gpgw fix review (PR for that fix closes the reported vuln; these are follow-ups, not regressions it introduced).
## 1. HMAC lacks per-message-type domain separation
`security.ComputeHMAC`/`ValidateHMAC` (internal/cluster/security/auth.go) sign `nonce \x00 nodeID \x00 clusterName \x00 timestamp` with **no message-type prefix**. Three handlers use this identical MAC: join, leave, and (as of the GHSA-p378 fix) heartbeat. There is no nonce-replay cache on this path (only `ReplicateSync` uses `nonceCache`), so within the 5-minute timestamp tolerance a captured `(AuthNonce, AuthTimestamp, AuthHMAC)` triple from any one of the three is a **valid MAC for the other two**.
Consequence: an on-path attacker who captures a signed *heartbeat* from node X can replay those auth fields inside a **leave** message for X → `handleLeaveNotify` (on the leader) calls `RemoveServer`+`RemoveNode`+`Unregister`, evicting X. This is gated by `cluster.tls_enabled` (the in-code warning at coordinator.go:207-208 already tells operators TLS is required to keep MACs off the wire), so it requires a no-TLS cluster + on-path position.
**Fix:** add a per-message-type domain-separation prefix to the signed message (the cache-invalidate variant already binds a distinguishing literal). Cover join/leave/heartbeat together. Bump no wire-compat concern if done in a coordinated release (all nodes same version).
## 2. doForward forwards client `Authorization`/`x-api-key` headers to peers
`internal/cluster/router.go` `doForward` copies **all** client headers — including `Authorization` and `x-api-key` — to the peer it forwards to (router.go:~354). This was the third item in GHSA-p378 (we could NOT reproduce it: in standard writer/reader topology nodes service ops locally and don't forward to a freshly-joined node). The GHSA-p378 fix (fail-closed on empty secret) removes the rogue-peer precondition, so this isn't independently exploitable today, but blindly forwarding caller credentials to peers is worth hardening defensively:
- Option A: strip client auth headers on forward and re-authenticate the forwarded request as the cluster identity.
- Option B: only forward to peers whose identity has been verified.
## Severity
Both Medium / defense-in-depth. Neither is a live exploit on a TLS-enabled, shared-secret cluster (the recommended config). File for a future cluster-auth hardening pass.
Contributor guide
Assessment
This issue has not been assessed yet.