Skip to content

Security Vulnerability in Query Anchor Logic - Drop Queries for Missing Seals in Existing Events #1145

@arilieb

Description

@arilieb

Problem Description

The current flow

  1. Query arrives with an anchor (seal reference)
  2. fetchAllSealingEventByEventSeal returns None if seal not found
  3. Query is escrowed regardless of why it wasn't found
  4. Query is re-processed later

The vulnerability

If the referenced event exists but the seal does not exist within it, the query should be dropped, not escrowed. The event is already finalized—the seal will never appear. Re-escrowing such queries allows an attacker to flood the system with queries containing fabricated seal references to existing events.

Legitimate escrow case

If the event itself doesn't exist yet, escrowing is appropriate—the event (with its seals) may arrive later.

Current Vulnerable Code Path

if anchor:
    if not self.db.fetchAllSealingEventByEventSeal(pre=pre, seal=anchor):
        self.escrowQueryNotFoundEvent(serder=serder, prefixer=source, sigers=sigers, cigars=cigars)  # VULNERABILITY
        # ... raises QueryNotFoundError

Proposed Solution

  1. Create Two New Fetch Functions
  • Function 1: fetchEventByEventSeal(pre, seal, sn=0)
    • Purpose: Find the event referenced by the seal (by pre and sn from the seal)
    • Returns: The event Serder if found, None if event doesn't exist
  • Function 2: fetchSealInEvent(event, seal)
    • Purpose: Check if a specific seal exists within a given event
    • Returns: True if seal found in event's anchor list, False otherwise
  1. Update Anchor Logic in processQuery
if anchor:
    event = self.db.fetchEventByEventSeal(pre=pre, seal=anchor)
    
    if event is None:
        # Event doesn't exist yet - legitimate escrow case
        self.escrowQueryNotFoundEvent(serder=serder, prefixer=source, sigers=sigers, cigars=cigars)
        msg = f"Query not found error on event route={route} SAID={serder.said}"
        logger.debug(msg)
        raise QueryNotFoundError(msg)
    
    if not self.db.fetchSealInEvent(event=event, seal=anchor):
        # Event exists but seal is not present - DROP, do not escrow
        msg = f"Seal not found in existing event route={route} SAID={serder.said}"
        logger.debug(msg)
        raise QueryNotFoundError(msg)
  1. Audit Other fetch...SealingEvent Functions
  • Investigate other fetch functions in baser to ensure they don't have similar vulnerabilities where the distinction between "container not found" vs "item not in container" matters for escrow decisions:
  • Review all fetchSeal functions
  • Identify call sites that escrow on failure
  • Determine if two-phase lookup is needed
  1. Preserve Original Function
  • Do not immediately remove fetchAllSealingEventByEventSeal (or its alias findAnchoringSealEvent) as it may be used appropriately elsewhere. Either:
    • Verify no other usages exist before removal, OR
    • Keep for backward compatibility

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions