Skip to content

Add rate limiting to sensitive endpoints #1029

Description

@AevumDecessus

Summary

The application has no rate limiting at the Django layer. No rate-limiting library is installed, no middleware is configured, and no decorators are applied to any view.

Priority Endpoints

  1. /admin/login/ - Unlimited password attempts. Primary login is Discord OAuth but any Django user with a password (superusers from createsuperuser) is vulnerable to brute-force.
  2. /stream/pub/stop, /stream/pub/start, /stream/pub/play - Stream key is sole auth factor. Key space is now ~1 trillion (PR Use cryptographic PRNG and expand wordlist for stream key generation #1024) but there's no lockout or backoff on failed attempts.
  3. /d/donations - Triggers update_donations_if_needed.delay() on every request. Unlimited requests can queue thousands of Celery tasks hitting the upstream DonorDrive API.

Current Mitigations

  • SWAG (NGINX) reverse proxy sits in front of the app and may provide some rate limiting via fail2ban, but this is not verified and is not defense-in-depth
  • Stream key entropy was improved to ~40 bits in PR Use cryptographic PRNG and expand wordlist for stream key generation #1024 (brute-force at 1000 req/s would take ~31.7 years)
  • Donation views are cached (@cache_page) so repeated identical requests don't re-trigger tasks, but cache-busting via varied query params bypasses this

Recommended Approach

django-ratelimit is the lightest option -- decorator-based, per-view control, uses the existing Redis cache backend. No migrations needed.

pip install django-ratelimit

Suggested rates:

  • /admin/login/ - 5 attempts per minute per IP
  • /stream/pub/* - 10 requests per minute per IP
  • /d/donations - 30 requests per minute per IP
  • /d/donations/tracked - 30 requests per minute per IP

Example:

from django_ratelimit.decorators import ratelimit

@ratelimit(key='ip', rate='10/m', method='POST', block=True)
@csrf_exempt
@require_POST
def stop(request):
    ...

Acceptance Criteria

  • django-ratelimit added to pyproject.toml and lockfiles
  • Stream control endpoints (/stream/pub/*) rate limited
  • Donation API endpoints rate limited
  • /admin/login/ rate limited (via middleware or decorator)
  • 429 responses returned when limit is exceeded
  • Tests verify rate limiting triggers on excessive requests

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions