diff options
Diffstat (limited to 'internal/handler/websocket/handler.go')
| -rw-r--r-- | internal/handler/websocket/handler.go | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/internal/handler/websocket/handler.go b/internal/handler/websocket/handler.go index 715e777..8daa89f 100644 --- a/internal/handler/websocket/handler.go +++ b/internal/handler/websocket/handler.go | |||
| @@ -299,6 +299,13 @@ func (h *Handler) handleEvent(ctx context.Context, conn *websocket.Conn, raw []j | |||
| 299 | pbEvent := NostrToPB(&event) | 299 | pbEvent := NostrToPB(&event) |
| 300 | canonicalJSON := event.Serialize() | 300 | canonicalJSON := event.Serialize() |
| 301 | 301 | ||
| 302 | // Reject non-core protocol kinds (spam, ephemeral, chat) | ||
| 303 | if !isAllowedKind(pbEvent.Kind) { | ||
| 304 | status = "ok" | ||
| 305 | h.sendOK(ctx, conn, event.ID, true, "rejected: kind not supported") | ||
| 306 | return nil | ||
| 307 | } | ||
| 308 | |||
| 302 | // Handle deletion events (kind 5) - process but don't store | 309 | // Handle deletion events (kind 5) - process but don't store |
| 303 | if pbEvent.Kind == 5 { | 310 | if pbEvent.Kind == 5 { |
| 304 | if err := h.store.ProcessDeletion(ctx, pbEvent); err != nil { | 311 | if err := h.store.ProcessDeletion(ctx, pbEvent); err != nil { |
| @@ -564,3 +571,38 @@ func getClientIP(r *http.Request) string { | |||
| 564 | // Fall back to RemoteAddr (direct connection or proxy IP) | 571 | // Fall back to RemoteAddr (direct connection or proxy IP) |
| 565 | return r.RemoteAddr | 572 | return r.RemoteAddr |
| 566 | } | 573 | } |
| 574 | |||
| 575 | // isAllowedKind returns true if the event kind is a core Nostr protocol kind. | ||
| 576 | // Rejects spam, ephemeral events, live chat, and other non-essential kinds. | ||
| 577 | func isAllowedKind(kind int32) bool { | ||
| 578 | // Core protocol kinds (NIP-01, NIP-02, etc.) | ||
| 579 | switch kind { | ||
| 580 | case 0: // Metadata/profile | ||
| 581 | return true | ||
| 582 | case 1: // Short text note | ||
| 583 | return true | ||
| 584 | case 3: // Contacts/following | ||
| 585 | return true | ||
| 586 | case 4: // Encrypted DM | ||
| 587 | return true | ||
| 588 | case 5: // Event deletion (handled separately) | ||
| 589 | return true | ||
| 590 | case 6: // Repost | ||
| 591 | return true | ||
| 592 | case 7: // Reaction | ||
| 593 | return true | ||
| 594 | case 9735: // Zap | ||
| 595 | return true | ||
| 596 | case 10000, 10001, 10002: // Mute lists, pin lists (NIP-51) | ||
| 597 | return true | ||
| 598 | case 10050: // Relay list metadata | ||
| 599 | return true | ||
| 600 | case 30023: // Long-form content (NIP-23) | ||
| 601 | return true | ||
| 602 | case 30078: // Application-specific data (NIP-78) | ||
| 603 | return true | ||
| 604 | default: | ||
| 605 | // Reject everything else (chat, ephemeral, spam) | ||
| 606 | return false | ||
| 607 | } | ||
| 608 | } | ||
