Files
openclaw/extensions/nostr
Tyler Yust 1007d71f0c fix: comprehensive BlueBubbles and channel cleanup (#11093)
* feat(bluebubbles): auto-strip markdown from outbound messages (#7402)

* fix(security): add timeout to webhook body reading (#6762)

Adds 30-second timeout to readBody() in voice-call, bluebubbles, and nostr
webhook handlers. Prevents Slow-Loris DoS (CWE-400, CVSS 7.5).
Merged with existing maxBytes protection in voice-call.

* fix(security): unify Error objects and lint fixes in webhook timeouts (#6762)

* fix: prevent plugins from auto-enabling without user consent (#3961)

Changes default plugin enabled state from true to false in enablePluginEntry().
Preserves existing enabled:true values. Fixes #3932.

* fix: apply hierarchical mediaMaxMb config to all channels (#8749)

Generalizes resolveAttachmentMaxBytes() to use account → channel → global
config resolution for all channels, not just BlueBubbles. Fixes #7847.

* fix(bluebubbles): sanitize attachment filenames against header injection (#10333)

Strip ", \r, \n, and \\ from filenames after path.basename() to prevent
multipart Content-Disposition header injection (CWE-93, CVSS 5.4).
Also adds sanitization to setGroupIconBlueBubbles which had zero filename
sanitization.

* fix(lint): exclude extensions/ from Oxlint preflight check (#9313)

Extensions use PluginRuntime|null patterns that trigger
no-redundant-type-constituents because PluginRuntime resolves to any.
Excluding extensions/ from Oxlint unblocks user upgrades.
Re-applies the approach from closed PR #10087.

* fix(bluebubbles): add tempGuid to createNewChatWithMessage payload (#7745)

Non-Private-API mode (AppleScript) requires tempGuid in send payloads.
The main sendMessageBlueBubbles already had it, but createNewChatWithMessage
was missing it, causing 400 errors for new chat creation without Private API.

* fix: send stop-typing signal when run ends with NO_REPLY (#8785)

Adds onCleanup callback to the typing controller that fires when the
controller is cleaned up while typing was active (e.g., after NO_REPLY).
Channels using createTypingCallbacks automatically get stop-typing on
cleanup. This prevents the typing indicator from lingering in group chats
when the agent decides not to reply.

* fix(telegram): deduplicate skill commands in multi-agent setup (#5717)

Two fixes:
1. Skip duplicate workspace dirs when listing skill commands across agents.
   Multiple agents sharing the same workspace would produce duplicate commands
   with _2, _3 suffixes.
2. Clear stale commands via deleteMyCommands before registering new ones.
   Commands from deleted skills now get cleaned up on restart.

* fix: add size limits to unbounded in-memory caches (#4948)

Adds max-size caps with oldest-entry eviction to prevent OOM in
long-running deployments:
- BlueBubbles serverInfoCache: 64 entries (already has TTL)
- Google Chat authCache: 32 entries
- Matrix directRoomCache: 1024 entries
- Discord presenceCache: 5000 entries per account

* fix: address review concerns (#11093)

- Chain deleteMyCommands → setMyCommands to prevent race condition (#5717)
- Rename enablePluginEntry to registerPluginEntry (now sets enabled: false)
- Add Slow-Loris timeout test for readJsonBody (#6023)
2026-02-07 05:00:55 -08:00
..
2026-02-07 00:44:32 -08:00
2026-02-07 00:44:32 -08:00
2026-01-31 21:13:13 +09:00

@openclaw/nostr

Nostr DM channel plugin for OpenClaw using NIP-04 encrypted direct messages.

Overview

This extension adds Nostr as a messaging channel to OpenClaw. It enables your bot to:

  • Receive encrypted DMs from Nostr users
  • Send encrypted responses back
  • Work with any NIP-04 compatible Nostr client (Damus, Amethyst, etc.)

Installation

openclaw plugins install @openclaw/nostr

Quick Setup

  1. Generate a Nostr keypair (if you don't have one):

    # Using nak CLI
    nak key generate
    
    # Or use any Nostr key generator
    
  2. Add to your config:

    {
      "channels": {
        "nostr": {
          "privateKey": "${NOSTR_PRIVATE_KEY}",
          "relays": ["wss://relay.damus.io", "wss://nos.lol"]
        }
      }
    }
    
  3. Set the environment variable:

    export NOSTR_PRIVATE_KEY="nsec1..."  # or hex format
    
  4. Restart the gateway

Configuration

Key Type Default Description
privateKey string required Bot's private key (nsec or hex format)
relays string[] ["wss://relay.damus.io", "wss://nos.lol"] WebSocket relay URLs
dmPolicy string "pairing" Access control: pairing, allowlist, open, disabled
allowFrom string[] [] Allowed sender pubkeys (npub or hex)
enabled boolean true Enable/disable the channel
name string - Display name for the account

Access Control

DM Policies

  • pairing (default): Unknown senders receive a pairing code to request access
  • allowlist: Only pubkeys in allowFrom can message the bot
  • open: Anyone can message the bot (use with caution)
  • disabled: DMs are disabled

Example: Allowlist Mode

{
  "channels": {
    "nostr": {
      "privateKey": "${NOSTR_PRIVATE_KEY}",
      "dmPolicy": "allowlist",
      "allowFrom": ["npub1abc...", "0123456789abcdef..."]
    }
  }
}

Testing

# Using strfry
docker run -p 7777:7777 ghcr.io/hoytech/strfry

# Configure openclaw to use local relay
"relays": ["ws://localhost:7777"]

Manual Test

  1. Start the gateway with Nostr configured
  2. Open Damus, Amethyst, or another Nostr client
  3. Send a DM to your bot's npub
  4. Verify the bot responds

Protocol Support

NIP Status Notes
NIP-01 Supported Basic event structure
NIP-04 Supported Encrypted DMs (kind:4)
NIP-17 Planned Gift-wrapped DMs (v2)

Security Notes

  • Private keys are never logged
  • Event signatures are verified before processing
  • Use environment variables for keys, never commit to config files
  • Consider using allowlist mode in production

Troubleshooting

Bot not receiving messages

  1. Verify private key is correctly configured
  2. Check relay connectivity
  3. Ensure enabled is not set to false
  4. Check the bot's public key matches what you're sending to

Messages not being delivered

  1. Check relay URLs are correct (must use wss://)
  2. Verify relays are online and accepting connections
  3. Check for rate limiting (reduce message frequency)

License

MIT