1
0
mirror of https://github.com/django/django.git synced 2025-03-12 18:30:48 +00:00

[5.2.x] Added security reporting guidelines.

Backport of 59353360590202fab04067e23214a825157c524b from main.
This commit is contained in:
Sarah Boyce 2025-02-21 11:26:10 +01:00
parent a39d0ff88f
commit 865337ae92
2 changed files with 135 additions and 0 deletions

View File

@ -43,6 +43,131 @@ the industry-standard 90 days. Confirmed vulnerabilities with a
.. _our public Trac instance: https://code.djangoproject.com/query .. _our public Trac instance: https://code.djangoproject.com/query
Reporting guidelines
--------------------
Include a runnable proof of concept
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Please privately share a minimal Django project or code snippet that
demonstrates the potential vulnerability. Include clear instructions on how to
set up, run, and reproduce the issue.
Please do not attach screenshots of code.
User input must be sanitized
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reports based on a failure to sanitize user input are not valid security
vulnerabilities. It is the developer's responsibility to properly handle user
input. This principle is explained in our :ref:`security documentation
<sanitize-user-input>`.
For example, the following is **not considered valid** because ``email`` has
not been sanitized::
from django.core.mail import send_mail
from django.http import JsonResponse
def my_proof_of_concept(request):
email = request.GET.get("email", "")
send_mail("Email subject", "Email body", email, ["admin@example.com"])
return JsonResponse(status=200)
Developers must **always validate and sanitize input** before using it. The
correct approach would be to use a Django form to ensure ``email`` is properly
validated::
from django import forms
from django.core.mail import send_mail
from django.http import JsonResponse
class EmailForm(forms.Form):
email = forms.EmailField()
def my_proof_of_concept(request):
form = EmailForm(request.GET)
if form.is_valid():
send_mail(
"Email subject",
"Email body",
form.cleaned_data["email"],
["admin@example.com"],
)
return JsonResponse(status=200)
return JsonResponse(form.errors, status=400)
Similarly, as Django's raw SQL constructs (such as :meth:`~.QuerySet.extra` and
:class:`.RawSQL` expression) provide developers with full control over the
query, they are insecure if user input is not properly handled. As explained in
our :ref:`security documentation <sql-injection-protection>`, it is the
developer's responsibility to safely process user input for these functions.
For instance, the following is **not considered valid** because ``query`` has
not been sanitized::
from django.shortcuts import HttpResponse
from .models import MyModel
def my_proof_of_concept(request):
query = request.GET.get("query", "")
q = MyModel.objects.extra(select={"id": query})
return HttpResponse(q.values())
Request headers and URLs must be under 8K bytes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To prevent denial-of-service (DoS) attacks, production-grade servers impose
limits on request header and URL sizes. For example, by default Gunicorn allows
up to roughly:
* `4k bytes for a URL`_
* `8K bytes for a request header`_
Other web servers, such as Nginx and Apache, have similar restrictions to
prevent excessive resource consumption.
Consequently, the Django security team will not consider reports that rely on
request headers or URLs exceeding 8K bytes, as such inputs are already
mitigated at the server level in production environments.
.. admonition:: :djadmin:`runserver` should never be used in production
Django's built-in development server does not enforce these limits because
it is not designed to be a production server.
.. _`4k bytes for a URL`: https://docs.gunicorn.org/en/stable/settings.html#limit-request-line
.. _`8k bytes for a request header`: https://docs.gunicorn.org/en/stable/settings.html#limit-request-field-size
The request body must be under 2.5 MB
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The :setting:`DATA_UPLOAD_MAX_MEMORY_SIZE` setting limits the default maximum
request body size to 2.5 MB.
As this is enforced on all production-grade Django projects by default, a proof
of concept must not exceed 2.5 MB in the request body to be considered valid.
Issues resulting from large, but potentially reasonable setting values, should
be reported using the `public ticket tracker`_ for hardening.
.. _public ticket tracker: https://code.djangoproject.com/
Code under test must feasibly exist in a Django project
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The proof of concept must plausibly occur in a production-grade Django
application, reflecting real-world scenarios and following standard development
practices.
Django contains many private and undocumented functions that are not part of
its public API. If a vulnerability depends on directly calling these internal
functions in an unsafe way, it will not be considered a valid security issue.
.. _security-report-evaluation: .. _security-report-evaluation:
How does Django evaluate a report How does Django evaluate a report

View File

@ -5,6 +5,16 @@ Security in Django
This document is an overview of Django's security features. It includes advice This document is an overview of Django's security features. It includes advice
on securing a Django-powered site. on securing a Django-powered site.
.. _sanitize-user-input:
Always sanitize user input
==========================
The golden rule of web application security is to never trust user-controlled
data. Hence, all user input should be sanitized before being used in your
application. See the :doc:`forms documentation </topics/forms/index>` for
details on validating user inputs in Django.
.. _cross-site-scripting: .. _cross-site-scripting:
Cross site scripting (XSS) protection Cross site scripting (XSS) protection