Skip to content

fix(security) : Add email validation, rate limiting & harden DEBUG default#502

Open
prince-shakyaa wants to merge 4 commits into
GenAI-Security-Project:mainfrom
prince-shakyaa:fix/auth-input-validation-rate-limiting
Open

fix(security) : Add email validation, rate limiting & harden DEBUG default#502
prince-shakyaa wants to merge 4 commits into
GenAI-Security-Project:mainfrom
prince-shakyaa:fix/auth-input-validation-rate-limiting

Conversation

@prince-shakyaa

@prince-shakyaa prince-shakyaa commented May 16, 2026

Copy link
Copy Markdown

Summary

Fixes two key security issues in the authentication layer:

  • Email format validation on the magic-link endpoint.
  • Per-IP rate limiting on the magic-link endpoint.

Note

Finding 3 (Insecure DEBUG Default) Excluded: After thorough evaluation, changing the default configuration fallback to DEBUG=False has been intentionally omitted from this PR. Changing it to False by default breaks local Capture-the-Flag (CTF) environments out of the box (e.g., SSRF validation strictly blocks localhost and private IP webhooks when DEBUG is False). To maintain an excellent local developer/player experience while preserving safety, DEBUG remains True by default, and production environments should continue to explicitly override it using DEBUG=false in their .env file as documented.

Fixes #501


Changes

finbot/apps/finbot/auth.py

1. Email format validation - Rejects non-email strings before hitting the DB or email service.

+ from pydantic import EmailStr, ValidationError
+
  email = email.lower().strip()
+
+ try:
+     EmailStr._validate(email)
+ except Exception:
+     return template_response(request, "auth-error.html", {
+         "error": "Invalid email",
+         "message": "Please enter a valid email address.",
+     })

2. Per-IP rate limiting - Sliding-window counter (5 req / 60 s) using only stdlib.
No new dependencies added. Comment in code explains how to upgrade to Redis-backed slowapi for multi-worker deployments.

+ _RATE_LIMIT_WINDOW = 60
+ _RATE_LIMIT_MAX    = 5
+ _rate_store: dict[str, list[float]] = defaultdict(list)
+ _rate_lock = Lock()
+
+ def _is_rate_limited(ip: str) -> bool: ...
+
  client_ip = request.client.host if request.client else "unknown"
+ if _is_rate_limited(client_ip):
+     return template_response(request, "auth-error.html", {
+         "error": "Too many requests",
+         "message": "Please wait a moment before requesting another sign-in link.",
+     })

Why This Matters

Before After Risk Removed
Any string accepted as email Validated against RFC 5321 format Orphaned DB rows, email service errors, unhandled exception leaks
No throttle on magic-link endpoint 5 req/min per IP Email flooding, inbox harassment, database DoS

Testing

  • POST /auth/magic-link with email=not-an-email → returns validation error page
  • POST /auth/magic-link called 6× in under 60 s from same IP → 6th request returns rate-limit error page
  • Valid email still works end-to-end (magic link sent, token stored)

Notes for Reviewers

  • Rate limiter is in-memory per-process. For a multi-worker Gunicorn setup this should be upgraded to a Redis-backed limiter. A # TODO comment is left in code.
  • pydantic[email] is already listed in pyproject.toml - no new dependency added.
  • DEBUG status preserved: The DEBUG default in config.py was kept as True to ensure local CTF challenge compatibility.
…ault

- Validate email format on POST /auth/magic-link using pydantic EmailStr
  before writing to DB or calling the email service. Invalid addresses now
  return a user-friendly error page instead of propagating garbage to the DB.

- Add a per-IP sliding-window rate limiter (5 req / 60 s) on the magic-link
  endpoint using stdlib only (no new dependencies). Prevents email flooding,
  inbox harassment, and unbounded MagicLinkToken table growth.
  A TODO comment documents the Redis-backed upgrade path for multi-worker use.

- Change DEBUG default from True to False in config.py so cloned instances
  do not silently start in hot-reload / verbose-traceback mode. Developers
  enable it explicitly via DEBUG=true in .env (already documented in
  .env.example).

Fixes #___
@prince-shakyaa

prince-shakyaa commented May 16, 2026

Copy link
Copy Markdown
Author

Hi @saikishu @e2hln
Fixed three backend security issues - missing email validation, no rate limiting on the magic-link endpoint, and DEBUG=True as the default. No new dependencies added, tested locally.
Thank You.

@prince-shakyaa prince-shakyaa changed the title [Security] Add email validation, rate limiting & harden DEBUG default May 18, 2026
@prince-shakyaa prince-shakyaa changed the title fix(Security) : Add email validation, rate limiting & harden DEBUG default May 18, 2026
Prince Shakya and others added 3 commits May 19, 2026 19:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant