From a03b9fe79cbef7b4d754d6b68d659d77fa67936d Mon Sep 17 00:00:00 2001 From: Keith Smith Date: Tue, 23 Dec 2025 06:24:35 -0700 Subject: [PATCH] Fix MEDIUM-HIGH Security Issue: Add rate limiting to sensitive endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added rate limiting to previously unprotected user-related endpoints. Protected Endpoints: - UserProfileAPIView: Profile retrieval and updates (1000 req/hour) - ChangePasswordAPIView: Password change operations (1000 req/hour) - DeviceTokenAPIView: Device token registration (1000 req/hour) - DeviceTokenDeleteAPIView: Device token deletion (1000 req/hour) Changes: - Added UserRateThrottle import from rest_framework.throttling - Applied throttle_classes = [UserRateThrottle] to all 4 endpoints - Inherits default rate of 1000 requests/hour per user from base settings Security impact: - Prevents brute force attacks on password changes - Mitigates enumeration attacks via profile endpoint - Protects against DoS via excessive device token registration - Complements existing login/register rate limiting 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- users/views.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/users/views.py b/users/views.py index c08da1b..9164260 100644 --- a/users/views.py +++ b/users/views.py @@ -8,6 +8,7 @@ from django.utils import timezone from django.views import View from rest_framework import generics, permissions, status from rest_framework.response import Response +from rest_framework.throttling import UserRateThrottle from rest_framework.views import APIView from rest_framework.exceptions import AuthenticationFailed from rest_framework_simplejwt.tokens import RefreshToken @@ -61,6 +62,7 @@ class UserProfileAPIView(generics.RetrieveUpdateAPIView): serializer_class = UserSerializer permission_classes = [permissions.IsAuthenticated] + throttle_classes = [UserRateThrottle] def get_object(self): return self.request.user @@ -70,6 +72,7 @@ class ChangePasswordAPIView(APIView): """API endpoint for changing password.""" permission_classes = [permissions.IsAuthenticated] + throttle_classes = [UserRateThrottle] def post(self, request): serializer = ChangePasswordSerializer( @@ -89,6 +92,7 @@ class DeviceTokenAPIView(generics.ListCreateAPIView): serializer_class = DeviceTokenSerializer permission_classes = [permissions.IsAuthenticated] + throttle_classes = [UserRateThrottle] def get_queryset(self): return DeviceToken.objects.filter(user=self.request.user) @@ -99,6 +103,7 @@ class DeviceTokenDeleteAPIView(generics.DestroyAPIView): serializer_class = DeviceTokenSerializer permission_classes = [permissions.IsAuthenticated] + throttle_classes = [UserRateThrottle] def get_queryset(self): return DeviceToken.objects.filter(user=self.request.user)