🚨 suggestion (security): Scope and conditions for disabling CSRF on /api/ may be too broad
This disables CSRF for all /api/ requests, including unsafe methods using session/cookie auth, which is a significant security risk. Please scope this more narrowly (e.g., only for specific views or subpaths that use token/JWT auth or other non-cookie mechanisms) and avoid relying on a hard-coded /api/ prefix that may change or not cover all API routes.
Suggested implementation:
from django.conf import settings
UNSAFE_METHODS = {"POST", "PUT", "PATCH", "DELETE"}
CSRF_EXEMPT_API_PREFIXES = tuple(
getattr(settings, "CSRF_EXEMPT_API_PREFIXES", ())
)
def _is_exempt_api_path(path: str) -> bool:
"""
Returns True if the given path is configured as CSRF-exempt for API usage.
Paths are configured via settings.CSRF_EXEMPT_API_PREFIXES as a tuple/list
of path prefixes (e.g. ["/api/auth/", "/api/webhooks/"]).
"""
return any(path.startswith(prefix) for prefix in CSRF_EXEMPT_API_PREFIXES)
def _has_non_cookie_auth(request) -> bool:
"""
Heuristically detect token/JWT/API-key style auth so we only disable CSRF
where cookie-based session auth is not expected.
"""
auth_header = request.META.get("HTTP_AUTHORIZATION", "")
api_key_header = request.META.get("HTTP_X_API_KEY", "")
if auth_header:
# Common patterns: "Bearer <token>", "Token <token>", "JWT <token>", etc.
return True
if api_key_header:
return True
return False
def disable_csrf(get_response):
"""
Middleware that selectively disables CSRF checks for API endpoints that:
- Match configured CSRF_EXEMPT_API_PREFIXES, and
- Use non-cookie authentication mechanisms (e.g. Authorization/API key), and
- Use an unsafe HTTP method.
This avoids disabling CSRF protection broadly for all `/api/` requests.
"""
def middleware(request):
if (
request.method in UNSAFE_METHODS
and _is_exempt_api_path(request.path)
and _has_non_cookie_auth(request)
):
setattr(request, "_dont_enforce_csrf_checks", True)
return get_response(request)
return middleware
To fully adopt this change, configure the specific API subpaths that should be CSRF-exempt in your Django settings, for example:
- In
settings.py (or appropriate settings module):
CSRF_EXEMPT_API_PREFIXES = [
"/api/auth/", # e.g. JWT login/refresh endpoints
"/api/webhooks/", # e.g. third-party webhooks using token signatures
]
Review and adjust CSRF_EXEMPT_API_PREFIXES so only endpoints using token/JWT/non-cookie auth are listed, and avoid including a broad /api/ prefix.
Originally posted by @sourcery-ai[bot] in #30 (comment)
🚨 suggestion (security): Scope and conditions for disabling CSRF on
/api/may be too broadThis disables CSRF for all
/api/requests, including unsafe methods using session/cookie auth, which is a significant security risk. Please scope this more narrowly (e.g., only for specific views or subpaths that use token/JWT auth or other non-cookie mechanisms) and avoid relying on a hard-coded/api/prefix that may change or not cover all API routes.Suggested implementation:
To fully adopt this change, configure the specific API subpaths that should be CSRF-exempt in your Django settings, for example:
settings.py(or appropriate settings module):Review and adjust
CSRF_EXEMPT_API_PREFIXESso only endpoints using token/JWT/non-cookie auth are listed, and avoid including a broad/api/prefix.Originally posted by @sourcery-ai[bot] in #30 (comment)