Introduction
The @csrf_exempt decorator is tempting for APIs and webhooks, but improper use creates serious vulnerabilities. Learn when exemption is safe and when it's not.
Key Concepts
csrf_exempt: Decorator that disables CSRF protection for a view.
Webhook Verification: Alternative security for external service callbacks.
Token Authentication: Auth method that doesn't require CSRF protection.
Real World Context
A common pattern in startups is to slap @csrf_exempt on views to "fix" 403 errors during development, then forget to remove it before production. This has led to real account takeover vulnerabilities where attackers forged requests against session-authenticated endpoints.
Deep Dive
When CSRF Exemption is SAFE
python# 1. Token-authenticated APIs (no cookies used) @api_view(['POST']) @authentication_classes([TokenAuthentication]) def api_endpoint(request): pass # Token auth doesn't use cookies # 2. Webhooks with signature verification @csrf_exempt def stripe_webhook(request): payload = request.body sig = request.headers.get('Stripe-Signature') try: event = stripe.Webhook.construct_event( payload, sig, webhook_secret ) except stripe.error.SignatureVerificationError: return HttpResponse(status=400) # Process verified webhook return HttpResponse(status=200)
When CSRF Exemption is DANGEROUS
python# DANGEROUS: Session auth + csrf_exempt @csrf_exempt def transfer_money(request): if request.user.is_authenticated: # Uses session cookie # Attacker can forge this request! transfer(request.user, request.POST['amount'], request.POST['to'])
Safe Pattern: Verify Webhooks
pythonimport hmac import hashlib def verify_webhook(request, secret): signature = request.headers.get('X-Webhook-Signature') expected = hmac.new( secret.encode(), request.body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(signature, expected)
Common Pitfalls
- Exempting a view "temporarily" during development — Temporary exemptions tend to ship to production; use token auth or fix the CSRF flow instead.
- Not verifying webhook signatures — @csrf_exempt alone doesn't authenticate the request; always verify the sender using HMAC signatures or provider-specific validation.
Best Practices
- Never exempt session-authenticated views: Use CSRF or switch to token auth.
- Always verify webhooks: Use signatures, not just @csrf_exempt.
- Document exemptions: Comment why each exemption is safe.
Summary
@csrf_exempt is safe ONLY when not using session authentication. For webhooks, always verify signatures. For APIs, use token authentication which doesn't need CSRF protection.