← Back to PRs

#21778: Nostr: enforce inbound DM policy and command authorization

by chansuke open 2026-02-20 10:46 View on GitHub →
channel: nostr size: M
## Summary Describe the problem and fix in 2–5 bullets: - Problem: Nostr inbound DM handling could bypass/incorrectly apply DM admission and command authorization logic. - Why it matters: unauthorized senders could trigger replies/commands, while some valid paired senders could be denied control commands. - What changed: inbound now enforces `dmPolicy`, uses effective allowlist (`config.allowFrom` + pairing allow-from store), normalizes `nostr:`-prefixed entries, and sets `CommandAuthorized` from `resolveControlCommandGate` using actual sender match. - What did NOT change (scope boundary): no new config keys, no protocol/relay changes, no token/secret handling changes, and no non-Nostr channel behavior changes. ## Change Type (select all) - [x] Bug fix - [ ] Feature - [ ] Refactor - [x] Docs - [x] Security hardening - [ ] Chore/infra ## Scope (select all touched areas) - [ ] Gateway / orchestration - [ ] Skills / tool execution - [x] Auth / tokens - [ ] Memory / storage - [x] Integrations - [ ] API / contracts - [ ] UI / DX - [ ] CI/CD / infra ## Linked Issue/PR ## User-visible / Behavior Changes List user-visible changes (including defaults/config). If none, write `None`. - Nostr DMs now respect `dmPolicy` before reply dispatch. - Effective allowlist matching now includes both configured `allowFrom` and pairing allow-from store entries. - `nostr:`-prefixed allowlist entries are normalized correctly for sender matching. - Control directives (e.g. `/model`, `/think`, `/verbose`) are authorized consistently with DM admission rules. ## Security Impact (required) - New permissions/capabilities? (`Yes/No`): **No** - Secrets/tokens handling changed? (`Yes/No`): **No** - New/changed network calls? (`Yes/No`): **No** - Command/tool execution surface changed? (`Yes/No`): **Yes** - Data access scope changed? (`Yes/No`): **No** - If any `Yes`, explain risk + mitigation: - The command surface is narrowed to intended authorized senders only. - Mitigation is policy-aligned gating (`dmPolicy` + effective allowlist sender match) before command authorization is granted. ## Repro + Verification ### Environment - OS: Linux 6.8.0-100-generic x86_64 - Runtime/container: Node v22.20.0, pnpm 8.7.4 - Model/provider: N/A (channel authorization path) - Integration/channel (if any): Nostr - Relevant config (redacted): `channels.nostr.accounts[].config.dmPolicy`, `allowFrom`, pairing allow-from store ### Steps 1. Configure a Nostr account with `dmPolicy` set to `pairing` or `allowlist` and populate `allowFrom` (including a `nostr:npub...` entry). 2. Send Nostr DMs from both allowed and unallowed pubkeys, including a control command message (e.g. `/model ...`). 3. Observe whether reply dispatch and command authorization follow policy and effective allowlist. ### Expected - Unauthorized senders are dropped (or pairing flow is triggered for pairing mode). - Allowed senders are admitted and control commands are authorized per policy. ### Actual - Targeted channel tests pass, and inbound logic now applies policy + effective allowlist before dispatch with aligned command authorization. ## Evidence Attach at least one: - [ ] Failing test/log before + passing after - [x] Trace/log snippets - [ ] Screenshot/recording - [ ] Perf numbers (if relevant) Trace/log snippet: ```text RUN v4.0.18 /home/chansuke/code/oss/openclaw-wt/update-todo ✓ extensions/nostr/src/channel.test.ts (21 tests) 12ms Test Files 1 passed (1) Tests 21 passed (21) ``` ## Human Verification (required) What you personally verified (not just CI), and how: - Verified scenarios: - Ran `pnpm vitest extensions/nostr/src/channel.test.ts` successfully. - Reviewed inbound path to confirm `dmPolicy` enforcement, effective allowlist merge, `nostr:` prefix normalization, and `CommandAuthorized` propagation. - Edge cases checked: - `allowFrom` entries with `nostr:` prefix. - Pairing-store-only allow entries. - Non-command vs command message path gating behavior. - What you did **not** verify: - Live relay end-to-end DM exchange on a real Nostr network. ## Compatibility / Migration - Backward compatible? (`Yes/No`): **Yes** - Config/env changes? (`Yes/No`): **No** - Migration needed? (`Yes/No`): **No** - If yes, exact upgrade steps: **N/A** ## Failure Recovery (if this breaks) - How to disable/revert this change quickly: - Revert commit `a6551c78f` (`git revert a6551c78f`). - Files/config to restore: - `extensions/nostr/src/channel.ts` - `CHANGELOG.md` (documentation only) - Known bad symptoms reviewers should watch for: - All Nostr DMs being dropped unexpectedly. - Allowed senders unable to use control directives. - Unexpected pairing prompts for already-allowed senders. ## Risks and Mitigations List only real risks for this PR. Add/remove entries as needed. If none, write `None`. - Risk: malformed/non-normalizable allowlist entries may not match expected senders. - Mitigation: normalization with fallback and explicit sender-match gating; debug logs on dropped sender paths. - Risk: pairing allow-from store read failures may temporarily reduce effective allowlist. - Mitigation: safe fallback behavior (deny by policy unless open) and existing pairing re-approval flow. <!-- greptile_comment --> <h3>Greptile Summary</h3> Enforces DM policy and command authorization for Nostr inbound messages to prevent unauthorized access. - Adds `dmPolicy` enforcement (`disabled`, `pairing`, `allowlist`, `open`) with early-return paths for unauthorized senders - Merges configured `allowFrom` with pairing store entries to create effective allowlist, normalizing `nostr:` prefixes correctly - Uses `resolveControlCommandGate` to align command authorization with sender admission rules - Replaces legacy inbound handler with proper `dispatchReplyWithBufferedBlockDispatcher` flow matching other channels <h3>Confidence Score: 4/5</h3> - Safe to merge with minor risk around edge cases in normalization fallback logic - Security hardening logic is sound and follows established patterns from other channels (Matrix, BlueBubbles). The authorization flow correctly enforces dmPolicy, merges allowlists, and gates commands. Tests pass. Minor risk exists around normalization error handling edge cases where malformed entries could reduce effective allowlist unexpectedly. - No files require special attention <sub>Last reviewed commit: a6551c7</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs