block / block/buzz

buzz-cli: messages thread validates --channel but never applies it to the root filter

Open
#6,006 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

`cmd_get_thread` validates `--channel` and then never applies it to one of the two filters it sends.

```rust
// crates/buzz-cli/src/commands/messages.rs
validate_uuid(channel_id)?; // --channel is validated

let reply_filter = json!({ "kinds": [...], "#h": [channel_id], "#e": [event_id], ... });
let root_filter = json!({ "ids": [event_id], "limit": 1 }); // <- no #h, no kinds
client.query_multi(&[reply_filter, root_filter]).await?;
```

Measured — event `57cabc93` lives in `platform-eng` (`ee5ec766`):

```
thread --channel ee5ec766 --event 57cabc93 -> rc=0, 11 events
thread --channel 3928fe05 --event 57cabc93 -> rc=0, 1 event, payload h-tag = ee5ec766
```

Asking the `buzz-security` channel for an event returns a `platform-eng` event at rc=0.

## This is a correctness bug, not a security one

The relay gates channel access independently — `crates/buzz-relay/src/api/bridge.rs:1132/1198 event_in_accessible_channel` — so this does not read events the caller could not otherwise read. Scope honesty: the non-member case was **not** tested, because every channel `channels list` returns for the auditing identity is readable (0 denials), so there was no negative control available.

The bug is that the CLI accepts a scope argument and silently doesn't apply it. `validate_uuid` on `--channel` is the tell that it was meant to matter.

A second consequence: the two filters have different kind scopes (the reply filter restricts kinds, the root filter does not), so a kind outside the reply list is visible to `messages thread` **iff** it is the id-root. Verified: a thread root that is itself a kind:7 is returned, while kind:7 replies e-tagging a kind:9 root are not. That makes "what kinds does this command return" unanswerable as a single list.

## Fix

Add `"#h": [channel_id]` to the root filter. Two lines. Consider whether the root filter should also carry a kind restriction, or whether the asymmetry is intentional and should be documented.

## Context

Found by @Dawn during an adversarial CLI audit; split out of #6004 (composite pagination cursors) to keep that PR to cursor-and-caps. Same failure family as the `--kinds` silent-default bug fixed in #6004 and the `--limit` silent truncation it works around: **the CLI accepts an argument, reports success, and does something other than what was asked.**

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.