Skip to content

moderation(L6): verify moderation reads against full request URL incl. query#1607

Merged
tlongwell-block merged 1 commit into
eva/community-moderationfrom
quinn/mod-read-auth
Jul 7, 2026
Merged

moderation(L6): verify moderation reads against full request URL incl. query#1607
tlongwell-block merged 1 commit into
eva/community-moderationfrom
quinn/mod-read-auth

Conversation

@tlongwell-block

Copy link
Copy Markdown
Collaborator

Fixes the NIP-98 read-auth mismatch Wren found in the #1591 L7 sweep: CLI signs the full request URL (query included), relay verified against the bare path only → buzz moderation reports / audit 401'd in normal use.

Fix: authorize_moderation_read takes the request's raw query (axum RawQuery) and appends it verbatim to the path before building the NIP-98 expected URL. restricted passes None, keeps bare-path expectation.

Tests (4, bridge.rs): query-bearing GET verifies iff expected URL carries the same query (reports?limit=20&status=open, audit?limit=20); anti-regression control proves the same event is rejected against the bare path; restricted still verifies query-less.

Validation on base 80594133: fmt --check, clippy -p buzz-relay --all-targets -D warnings, buzz-relay --lib 503/503 green. Delta is bridge.rs only, +157/-5.

Co-authored-by: Tyler Longwell tlongwell@block.xyz
Signed-off-by: Tyler Longwell tlongwell@block.xyz

…. query

Wren's L7 sweep (#1591) found a NIP-98 auth mismatch that 401'd
`buzz moderation reports` and `audit` in normal use: the CLI signs the
full request URL — query string included (`?limit=…&status=…`) — but the
relay reconstructed the expected URL from the bare path only, and
buzz-auth URL normalization preserves query strings, so they never
matched. `restricted` was unaffected (no query).

Fix: `authorize_moderation_read` now takes the request's raw query
(axum `RawQuery`) and appends it verbatim to the path before building the
NIP-98 expected URL, so the relay verifies against the actual request URI
the client signed. Verbatim (not re-parsed) keeps the match byte-exact
regardless of param order/encoding. `restricted` passes `None` and keeps
its bare-path expectation. This is the direction Wren recommended:
verifying the full request URL keeps future filtered reads honest.

Regression coverage (4 tests, bridge.rs): a query-bearing GET verifies
iff the expected URL carries the same query (`reports?limit=20&status=open`,
`audit?limit=20`); an anti-regression control proves the same event is
rejected with a URL mismatch against the bare path (the pre-fix behavior);
and `restricted` still verifies query-less. A test-local helper mirrors
the production query-reconstruction so the seam is pinned without a DB
harness.

Validation on base 8059413 (toolchain 1.95.0, PATH=repo bin): fmt
--check, clippy -p buzz-relay --all-targets -D warnings, test -p
buzz-relay --lib all green (503 passed / 0 failed / 2 ignored — 499 prior
+ 4 new). git diff --check clean. Delta is bridge.rs only, +157/-5.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
@tlongwell-block
tlongwell-block merged commit 9da503f into eva/community-moderation Jul 7, 2026
22 of 28 checks passed
@tlongwell-block
tlongwell-block deleted the quinn/mod-read-auth branch July 7, 2026 20:16
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.

1 participant