fix: filter invalid relay URLs from event tags (#217)

* fix: filter invalid relay URLs from event tags

Add validation to prevent invalid URLs from being used as relay hints.
The issue occurred when "r" tags containing non-relay URLs (like
https://(strangelove@basspistol.org/) were being extracted and used
as relay connection targets.

Changes:
- Add isValidRelayURL() helper to validate relay URLs (must have ws://
  or wss:// protocol and valid URL structure)
- Update extractRelayContext() in loaders.ts to filter r-tags, e-tag
  relay hints, and a-tag relay hints using the new validator
- Add comprehensive tests for isValidRelayURL()

https://claude.ai/code/session_01Ca2fKD2r4wHKRD8rcRohj9

* refactor: use applesauce isSafeRelayURL for relay URL validation

Refactor relay URL validation to use applesauce's isSafeRelayURL helper
which provides a fast regex-based check for valid websocket URLs.

Changes:
- Update isValidRelayURL in relay-url.ts to use isSafeRelayURL as fast
  path, with URL constructor fallback for IP addresses
- Re-export isSafeRelayURL from relay-url.ts for convenience
- Update loaders.ts to use isSafeRelayURL directly from applesauce
- Add relay URL validation to:
  - nostr-utils.ts: getEventPointerFromQTag (q-tag relay hints)
  - zapstore-helpers.ts: getAppReferences (a-tag relay hints)
  - nip89-helpers.ts: getHandlerReferences (a-tag relay hints)
  - PublicChatsRenderer.tsx: extractGroups (group relay URLs)

This ensures consistent validation across all relay URL extraction points
using applesauce's battle-tested validation.

https://claude.ai/code/session_01Ca2fKD2r4wHKRD8rcRohj9

* chore: remove unused isSafeRelayURL re-export

The re-export was added but all consumers import directly from
applesauce-core/helpers/relays instead.

https://claude.ai/code/session_01Ca2fKD2r4wHKRD8rcRohj9

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Alejandro
2026-01-27 10:59:26 +01:00
committed by GitHub
parent 3f3ebcf5f6
commit a28ffc1ec3
7 changed files with 195 additions and 13 deletions

View File

@@ -6,6 +6,7 @@ import { GroupLink } from "../GroupLink";
import eventStore from "@/services/event-store";
import pool from "@/services/relay-pool";
import type { NostrEvent } from "@/types/nostr";
import { isSafeRelayURL } from "applesauce-core/helpers/relays";
/**
* Extract group references from a kind 10009 event
@@ -19,9 +20,17 @@ function extractGroups(event: { tags: string[][] }): Array<{
for (const tag of event.tags) {
if (tag[0] === "group" && tag[1] && tag[2]) {
// Only include groups with valid relay URLs
const relayUrl = tag[2];
if (!isSafeRelayURL(relayUrl)) {
console.warn(
`[PublicChatsRenderer] Skipping group with invalid relay URL: ${relayUrl}`,
);
continue;
}
groups.push({
groupId: tag[1],
relayUrl: tag[2],
relayUrl,
});
}
}