Skip to content

fix(tightbeam)!: close audit defects and give loose functions owners - #56

Open
sephynox wants to merge 2 commits into
fix/audit-phase1-2from
fix/audit-phase2
Open

sephynox wants to merge 2 commits into
fix/audit-phase1-2from
fix/audit-phase2

Conversation

@sephynox

@sephynox sephynox commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Summary

A hand-written RouterPolicy could decode an encrypted or compressed body, because the cleartext guard lived only inside the routes! macro expansion rather than on the trait. This branch closes that along with the rest of the phase 1-2 audit findings, then moves every domain operation onto an owner type so each invariant it relies on has exactly one home.

Related Issues

None

Changes Made

  • RouterPolicy::dispatch now rejects encrypted and compressed bodies
  • Per-signer circuit breakers key on the transport-proven peer
  • A relay hop is spent when the relayed envelope is constructed
  • 53 public free functions became methods on their owning types

Testing

  • make test-all: passes

Breaking Changes

  • Implement RouterPolicy::dispatch_cleartext, not dispatch. The guard runs in dispatch.
  • Removed free functions are now methods: canonical_bytes(&urn) becomes urn.canonical_bytes().

Note

Medium Risk
Changes federation gateway registration, signer binding, and relay hop accounting on security-sensitive paths; most other edits are API relocation with matching test updates.

Overview
This PR finishes the phase 1–2 audit follow-up: tighten cluster control-plane identity and move dozens of loose helpers onto the types that own their invariants, with fuzz harnesses and clients updated to the new method style (urn.canonical_bytes(), Version::V0.compose(), etc.).

Hive registration and updates now require a DER signer on every register call; HiveEntry.signer_id is mandatory and re-registration only accepts the originally bound signer. Unsigned registration frames are refused, and HiveRegistry::signer_matches centralizes update attribution (CWE-639).

Relay forwarding spends hop budget when minting HopBudget::relayed_work / relayed_route, and ClusterError::forward_status maps forward failures to the right TransitStatus for callers. Colony membership and certificate helpers live on ColonyNamespace and Certificate::fingerprint_id; work wrapping uses ClusterWorkRequest::transport_frame / ClusterWorkResponse::served_reply.

Gateway runtime consolidates TLS identity (ClusterTlsConfig::identity), outbound pools (PoolConfig::build_cluster_pools), address-update parsing, export warnings, and gossip advertise/reconcile into GossipBeat / ClusterConfig methods—behavior preserved, structure grouped by owner.

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

@sephynox sephynox self-assigned this Sep 7, 2026
@sephynox sephynox added the bug Something isn't working label Sep 7, 2026
@sephynox

sephynox commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

@cursor bugbot and security agent, I find it hard to believe there were no issues found??

@cursor

cursor Bot commented Sep 7, 2026

Copy link
Copy Markdown

There were issues. Bugbot was wrong to treat this as clean.

The claimed cleartext fix was still bypassable: dispatch_cleartext took a raw Arc<Frame>, so a hand-written policy could decode an encrypted body without ensure_cleartext. That method now takes a CleartextFrame that can only be minted after the guard. Hive registration was also fail-open: a verified frame whose signer id did not encode installed an unbound hive, and an unbound hive accepts any later signer. Registration now refuses instead of binding None. A hand-written NaiveRouter plus CleartextFrame::admit both reject confidential frames (7 router tests, 5 registry tests).

Hop spend on honest gateways, transport-keyed circuit breakers, and cert-bound colony membership hold. Residuals I did not change: the hop count is still unauthenticated wire data, claimed gateway_addr is not proven until this gateway probes, OctetString handshake attributes are pinned to RECEIPT_ACK, and anonymous sessions share one breaker without mTLS. GitHub CI on this branch is still running.

Open in Web Open in Cursor 

@cursor

cursor Bot commented Sep 8, 2026

Copy link
Copy Markdown

Security review of this PR found real issues; they are not “no findings.”

Fixed on this branch

  1. Cleartext dispatch was still bypassable (CWE-345). RouterPolicy::dispatch ran ensure_cleartext, but dispatch_cleartext took a raw Arc<Frame>. A hand-written policy or a direct call could decode an encrypted or compressed body. dispatch_cleartext now takes a CleartextFrame that can only be minted after the guard.
  2. Hive registration could bind no signer (CWE-639). After a verified hive-origin frame, Frame::signer_id() returning None installed an unbound hive. HiveRegistry admits any later signer onto an unbound hive. Registration now refuses when the signer identifier does not encode.

Looked at, not a regression in this commit

  • Honest-gateway hop spend via HopBudget::relayed_* is correct; into_relayed / public hops_remaining remain a wire-level stamp (unauthenticated hop count is documented defense-in-depth; export still keys first-party on trust-store identity).
  • Circuit breakers already key on ProvenPeer, not frame SID.
  • Direct peer ads require some colony SAN in this namespace, not equality with the local colony URN. Gossip flood/reconcile already require equality. That split matches the federation-vs-flood docs; changing ads would be a behavior change.

Residuals (pre-existing / design)

  • Unauthenticated hop counter can be reset by a malicious peer (clamped per hop by max_hops).
  • Claimed gateway_addr on a signed peer ad is not proven until this gateway’s own probe.
  • impl AttributePayload for OctetString is pinned to RECEIPT_ACK (encode-side footgun, fail-closed on decode of the wrong OID).
  • Shared ProvenPeer::ANONYMOUS breaker when the hive control plane is not mTLS.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

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 high 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 f270acb. Configure here.

Comment thread tightbeam/src/colony/hive/gates.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant