Skip to content

SECURITY: fakeVerifyEvent exported as public API enables silent signature bypass #62

Description

@hzrd149

Summary

Severity: MEDIUM
Component: packages/core/src/helpers/event.ts:124-127
Affects: Any consumer using applesauce-core

The function `fakeVerifyEvent()` is exported as part of the public API. It sets an event's `verifiedSymbol` to `true` without performing any cryptographic verification. Combined with `setVerifyWrappedEventMethod()`, it provides a one-line way to globally disable all signature verification in gift wraps, zaps, and shared events.

Root Cause

// event.ts:124-127
/** Sets events verified flag without checking anything */
export function fakeVerifyEvent(event: NostrEvent): event is VerifiedEvent {
  event[verifiedSymbol] = true;
  return true;
}

This function is re-exported from the package's public entry point and can be combined with:

// Globally disable all wrapped event verification in one line:
setVerifyWrappedEventMethod(fakeVerifyEvent);

Or used to bypass EventStore verification:

eventStore.verifyEvent = fakeVerifyEvent;

The git history shows this was previously used in production code (`packages/better-sqlite3/src/relay.ts`, removed in commit 3d9e03b).

Impact

  1. Supply chain risk: If a dependency or middleware calls `setVerifyWrappedEventMethod(fakeVerifyEvent)`, all signature verification for zaps, gift wraps, and shared events is silently disabled across the application.
  2. Accidental misuse: The function name "fakeVerifyEvent" suggests testing use, but it's exported alongside production functions without any warning mechanism.
  3. Prior production use: The function was previously used in production relay code, demonstrating that misuse is not hypothetical.

Verification

import { fakeVerifyEvent, setVerifyWrappedEventMethod } from "applesauce-core/helpers";

// Both are publicly accessible
console.log(typeof fakeVerifyEvent);           // "function"
console.log(typeof setVerifyWrappedEventMethod); // "function"

// One line to disable all verification globally:
setVerifyWrappedEventMethod(fakeVerifyEvent);

Suggested Fix

Option A: Remove from public exports, keep internal for tests only:

// Move to a test utility file, don't export from main package

Option B: Add runtime warning:

export function fakeVerifyEvent(event: NostrEvent): event is VerifiedEvent {
  if (process.env.NODE_ENV !== "test") {
    console.warn("fakeVerifyEvent: bypassing signature verification - DO NOT USE IN PRODUCTION");
  }
  event[verifiedSymbol] = true;
  return true;
}

Option C: At minimum, rename to make the danger obvious:

export function UNSAFE_skipVerification(event: NostrEvent): event is VerifiedEvent { ... }

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions