Skip to content

NIP-46 Security: Bunker URL Secret Requirement Implementation #3

@pretyflaco

Description

@pretyflaco

Summary

Implemented security protection against the "Mike Dilger Attack" in NIP-46 remote signer authentication by requiring secret parameter in all bunker:// URLs.

Background

The Vulnerability

In the signer-initiated flow (bunker://), an attacker monitoring NIP-46 relays could:

  1. Observe a legitimate nostrconnect:// request from our app
  2. Race to send a malicious bunker:// URL without a secret
  3. If the user approves the wrong connection, the attacker gains signing access

The Fix

All bunker:// URLs must now include a secret parameter. This is enforced in NostrConnectServiceNDK.js:

// SECURITY: For bunker:// URLs, require a secret to prevent hijacking
if (inputType === 'bunker' && !secret) {
  return {
    success: false,
    error: 'Security: Bunker URL requires a secret parameter',
    securityRejection: true,
    noSecret: true
  };
}

Changes Made

Code

  • lib/nostr/NostrConnectServiceNDK.js - Added security check (~line 237)
  • components/auth/NostrConnectModal.js - Added security rejection UI

Tests

  • Created e2e/tests/auth/nip46-security.spec.ts with 11 comprehensive tests:
    • Bunker URL security validation (4 tests)
    • Console security logging (1 test)
    • QR code flow (3 tests)
    • Modal UI (3 tests)

Documentation

  • Updated NIP46_PORTAL_INTEGRATION.md with:
    • Implementation status (now "Implemented")
    • Security measures explanation
    • Testing instructions
    • Supported signer apps

Testing Results

Manual Testing

  • nsec.app - Bunker URL with secret: Working
  • Amber - Bunker URL with secret: Security check passed, connection attempted (timed out as expected without app open)
  • Portal - Bunker URL with secret: Security check passed, connection attempted

E2E Tests

11 passed (9.8s)

User Experience

When a bunker URL without a secret is entered, users see:

  1. "Connection Failed" warning
  2. "Security Protection" explanation
  3. Instructions for getting secure bunker URLs from different signer apps
  4. "Try Again" button

Compatibility Notes

Relay URL Formatting

Different signers use different formats:

  • Amber: Unencoded URLs (relay=wss://relay.nsec.app/)
  • Portal: URL-encoded (relay=wss%3A%2F%2Frelay.damus.io)

Both formats work correctly with our implementation.

Secret Formats

  • Amber: Short hex (6 chars)
  • nsec.app: 32-char hex
  • Portal: UUID format (36 chars)

All formats are accepted as long as the secret is non-empty.

Related

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions