Skip to content

auth_audit_logs records no IP on any row, so there is nothing to rate-limit or block on #609

Description

@TortoiseWolfe

The finding

Every row in auth_audit_logs has ip_address = null and user_agent = null on the
paths that matter. Across 7,665 rows:

sign_in_failed          4172   ip_address: all null
password_reset_request   934   ip_address: all null
sign_up                  103   ip_address: all null, user_agent: all null

The user_agent column is populated on sign_in_failed (4,113 of 4,172 share one
Windows/Chrome string), but it is null on sign_up, and ip_address is null
everywhere.

Why it matters now

#608 documents 5,106 junk auth calls against production. There is nothing in this
table to block on.
No IP, so no per-origin throttle, no ban list, no ASN analysis,
no way to tell one attacker from many. The audit trail records that we were attacked
and nothing about who.

This is not hypothetical bookkeeping — it is the direct blocker on fixing #608
properly. Any rate limit built today can only key on email or on a global counter,
both of which an attacker rotating addresses walks straight past.

Scope

Whatever writes these rows needs the request IP threaded through. Supabase Edge
Functions receive it on x-forwarded-for; a trigger firing inside Postgres does not
have it and cannot get it, so if the write happens in-database the capture point has
to move.

Acceptance

  • A failed sign-in from a known origin writes a row whose ip_address matches that
    origin. Assert the value, not that the column is non-null — a hardcoded
    '0.0.0.0' would satisfy a null check and still be useless.
  • sign_up rows carry user_agent like sign_in_failed already does.

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