From f59073e58932cadb30ba705c230cd5123ae0cbe6 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Wed, 1 Apr 2026 13:31:33 -0400 Subject: [PATCH] fix(nip05): add configurable limits for relays per user and identity listing Adds max_relays_per_user (default: 10) to prevent users from attaching excessive relay URLs that inflate .well-known/nostr.json responses. Enforced in both claimUsername and updateRelays. Reduces the no-name listing limit from hardcoded 1000 to configurable max_identities_listing (default: 100) for the /.well-known/nostr.json endpoint when no ?name= parameter is provided. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/extensions/nip05/managers/nip05Manager.ts | 21 ++++++++++++------- src/extensions/nip05/types.ts | 6 ++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/extensions/nip05/managers/nip05Manager.ts b/src/extensions/nip05/managers/nip05Manager.ts index d83fef1c..4eba8225 100644 --- a/src/extensions/nip05/managers/nip05Manager.ts +++ b/src/extensions/nip05/managers/nip05Manager.ts @@ -27,7 +27,9 @@ const DEFAULT_CONFIG: Required = { min_username_length: 1, reserved_usernames: ['admin', 'root', 'system', 'support', 'help', 'info', 'contact', 'abuse', 'postmaster', 'webmaster', 'hostmaster', 'noreply', 'no-reply', 'null', 'undefined', 'api', 'www', 'mail', 'ftp', 'ssh', 'test', 'demo'], include_relays: true, - default_relays: [] + default_relays: [], + max_relays_per_user: 10, + max_identities_listing: 100 } /** @@ -99,11 +101,15 @@ function validateUsername(username: string, config: Required): User /** * Validate relay URLs */ -function validateRelays(relays: string[]): UsernameValidation { +function validateRelays(relays: string[], maxRelays?: number): UsernameValidation { if (!Array.isArray(relays)) { return { valid: false, error: 'Relays must be an array' } } + if (maxRelays && relays.length > maxRelays) { + return { valid: false, error: `Too many relays (max ${maxRelays})` } + } + for (const relay of relays) { if (typeof relay !== 'string') { return { valid: false, error: 'Each relay must be a string' } @@ -166,7 +172,7 @@ export class Nip05Manager { // Validate relays if provided const relays = request.relays || this.config.default_relays if (relays.length > 0) { - const relayValidation = validateRelays(relays) + const relayValidation = validateRelays(relays, this.config.max_relays_per_user) if (!relayValidation.valid) { throw new Error(relayValidation.error) } @@ -241,7 +247,7 @@ export class Nip05Manager { request: UpdateRelaysRequest ): Promise { // Validate relays - const validation = validateRelays(request.relays) + const validation = validateRelays(request.relays, this.config.max_relays_per_user) if (!validation.valid) { throw new Error(validation.error) } @@ -361,10 +367,11 @@ export class Nip05Manager { } } } else { - // Return all active identities (with reasonable limit) + // Return all active identities (with configurable limit) + const limit = this.config.max_identities_listing const rows = await this.db.query( - `SELECT * FROM identities WHERE application_id = ? AND is_active = 1 LIMIT 1000`, - [applicationId] + `SELECT * FROM identities WHERE application_id = ? AND is_active = 1 LIMIT ?`, + [applicationId, limit] ) for (const row of rows) { diff --git a/src/extensions/nip05/types.ts b/src/extensions/nip05/types.ts index 93967f4c..6836f714 100644 --- a/src/extensions/nip05/types.ts +++ b/src/extensions/nip05/types.ts @@ -119,6 +119,12 @@ export interface Nip05Config { /** Default relays to suggest for new users */ default_relays?: string[] + + /** Maximum number of relays per user (default: 10) */ + max_relays_per_user?: number + + /** Maximum number of identities returned when no name query param is provided (default: 100) */ + max_identities_listing?: number } /**