Skip to content

[Audit] Log rate-limit denials #536

@2witstudios

Description

@2witstudios

Summary

Rate-limit denials in login flows return 429 without emitting dedicated security/audit events into immutable security logs.

Evidence

  • Web login route:
    • apps/web/src/app/api/auth/login/route.ts:94 returns 429 for IP limit.
    • apps/web/src/app/api/auth/login/route.ts:111 returns 429 for email limit.
    • Neither branch records logAuthEvent, logSecurityEvent, or securityAudit event before returning.
  • Mobile login route mirrors this behavior:
    • apps/web/src/app/api/auth/mobile/login/route.ts:51 and apps/web/src/app/api/auth/mobile/login/route.ts:68.
  • The security audit service already supports this event class:
    • packages/lib/src/audit/security-audit.ts:364 (logRateLimited).

Problem

Brute-force and credential-stuffing pressure that triggers throttling is not captured in tamper-evident audit records for login endpoints.

Enterprise Impact

  • “Inconsistent security-event coverage” concern.
  • Weaker forensic timeline for auth abuse incidents.

Proposed Work

  1. Emit a security event on both IP and email limiter denials in login handlers.
  2. Include relevant details (endpoint, dimension ip/email, hashed or masked identifier, retryAfter, requestId, ip).
  3. Route events into immutable audit chain (security.rate.limited) in addition to standard logs.
  4. Apply parity across web and mobile login handlers.

Acceptance Criteria

  • Every 429 from login rate limiting emits a security event before response.
  • Event is persisted in security_audit_log with eventType = security.rate.limited.
  • Tests assert event emission for both IP-limited and email-limited branches.
  • Sensitive identifiers remain masked or hashed in event details.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions