Skip to content

Security: harden cluster admin_proof replay without breaking plaintext accounting - #169

Open
cursor[bot] wants to merge 8 commits into
mainfrom
cursor/application-security-review-2fc5
Open

Security: harden cluster admin_proof replay without breaking plaintext accounting#169
cursor[bot] wants to merge 8 commits into
mainfrom
cursor/application-security-review-2fc5

Conversation

@cursor

@cursor cursor Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Harden cluster admin_proof replay handling while preserving the existing plaintext cluster accounting behavior.

Security

  • Track recently accepted admin_proof digests per node for 10 minutes.
  • Reject an already-used proof so captured ClientWrite/membership proofs cannot simply be replayed while the API token is unchanged.

Plaintext cluster behavior

  • Keep heartbeat publisher/player/per-stream/per-viewer session caches enabled when mTLS is off.
  • Plaintext clustering continues to use CLUSTER_SECRET + Raft membership as its documented trust boundary; mTLS adds stronger per-node certificate identity.
  • This avoids breaking cluster-wide publisher/player totals, viewer/session accounting, stream stats, and drain/delete behavior for the default CLUSTER_TLS_ENABLED=false setup.

The earlier version of this PR disabled all remote session-count caching for plaintext clusters; that regression has been removed.


Note

Medium Risk
Touches cluster authentication and admin/join forwarding paths; incorrect replay or join consumption logic could block legitimate ops or leave a narrow replay window.

Overview
Hardens cluster admin_proof handling so captured control-plane proofs cannot be replayed while the API bearer token is unchanged.

Proofs are minted as {nonce}.{mac}, where the MAC covers {nonce}:{payload}, so each legitimate retry gets a new cache key but a stolen proof cannot be re-signed. Each node keeps a 10-minute used_admin_proofs map: non-join proofs are marked used on first successful verification; Join: proofs stay retryable until accept_join (or successful leader forward) calls consume_admin_proof.

Plaintext clustering still records heartbeat publisher/player and per-stream/per-viewer counts on every node (documented as required for totals, limits, and drain/delete accounting); mTLS-only behavior for updating routing addresses from heartbeats is unchanged.

Adds unit tests for proof minting, TTL purge, and deterministic admin_proof (motivating the replay cache). Cargo.lock bumps minor dependency versions only.

Reviewed by Cursor Bugbot for commit 40922e3. Bugbot is set up for automated code reviews on this repo. Configure here.

cursoragent and others added 3 commits August 17, 2026 02:09
…eat counts

- Track recently accepted admin_proof digests per node so captured
  ClientWrite/membership proofs cannot be replayed while the API token
  is unchanged.
- Ignore heartbeat-supplied session counts on plaintext clusters; only
  mTLS-bound peers may update remote play/publish load used for admission.

Co-authored-by: Alexander Wagner <info@alexanderwagnerdev.com>
@AlexanderWagnerDev AlexanderWagnerDev changed the title Security: cluster admin_proof replay and heartbeat session-count hardening Security: harden cluster admin_proof replay without breaking plaintext accounting Aug 19, 2026
@AlexanderWagnerDev
AlexanderWagnerDev marked this pull request as ready for review August 19, 2026 04:57

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit af27deb. Configure here.

Comment thread src/cluster/manager.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants