Skip to content

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

Open
prince-shakyaa wants to merge 2 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 2 commits into
GenAI-Security-Project:mainfrom
prince-shakyaa:fix/auth-input-validation-rate-limiting

Conversation

@prince-shakyaa
Copy link
Copy Markdown

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

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
Copy link
Copy Markdown
Author

prince-shakyaa commented May 16, 2026

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 fix(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 fix(security) : Add email validation, rate limiting & harden DEBUG default May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security] Missing Input Validation, Rate Limiting, and Insecure DEBUG Default

1 participant