Denial of Service vulnerability in django-filter
Description
django-filter is a generic system for filtering Django QuerySets based on user selections. In django-filter before version 2.4.0, automatically generated NumberFilter instances, whose value was later converted to an integer, were subject to potential DoS from maliciously input using exponential format with sufficiently large exponents. Version 2.4.0+ applies a MaxValueValidator with a a default limit_value of 1e50 to the form field used by NumberFilter instances. In addition, NumberFilter implements the new get_max_validator() which should return a configured validator instance to customise the limit, or else None to disable the additional validation. Users may manually apply an equivalent validator if they are not able to upgrade.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
django-filterPyPI | < 2.4.0 | 2.4.0 |
Affected products
1- Range: < 2.4.0
Patches
1340cf7a23a2bVersion 2.4 (#1272)
9 files changed · +68 −33
.bumpversion.cfg+0 −24 removed@@ -1,24 +0,0 @@ -[bumpversion] -current_version = 2.3.0 -commit = False -tag = False -parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\.(?P<release>[a-z]+)(?P<num>\d+))? -serialize = - {major}.{minor}.{patch}.{release}{num} - {major}.{minor}.{patch} - -[bumpversion:file:django_filters/__init__.py] - -[bumpversion:file:setup.py] - -[bumpversion:file:docs/conf.py] - -[bumpversion:part:release] -optional_value = final -values = - dev - final - -[bumpversion:part:num] -first_value = 1 -
CHANGES.rst+17 −0 modified@@ -1,3 +1,20 @@ +Version 2.4.0 (2020-9-27) +-------------------------- + +* SECURITY: Added a ``MaxValueValidator`` to the form field for + ``NumberFilter``. This prevents a potential DoS attack if numbers with very + large exponents were subsequently converted to integers. + + The default limit value for the validator is ``1e50``. + + The new ``NumberFilter.get_max_validator()`` allows customising the used + validator, and may return ``None`` to disable the validation entirely. + +* Added testing against Django 3.1 and Python 3.9. + + In addition tests against Django main development branch are now required to + pass. + Version 2.3.0 (2020-6-5) ------------------------
django_filters/filters.py+18 −0 modified@@ -2,6 +2,7 @@ from datetime import timedelta from django import forms +from django.core.validators import MaxValueValidator from django.db.models import Q from django.db.models.constants import LOOKUP_SEP from django.forms.utils import pretty_name @@ -357,6 +358,23 @@ class ModelMultipleChoiceFilter(QuerySetRequestMixin, MultipleChoiceFilter): class NumberFilter(Filter): field_class = forms.DecimalField + def get_max_validator(self): + """ + Return a MaxValueValidator for the field, or None to disable. + """ + return MaxValueValidator(1e50) + + @property + def field(self): + if not hasattr(self, '_field'): + field = super().field + max_validator = self.get_max_validator() + if max_validator: + field.validators.append(max_validator) + + self._field = field + return self._field + class NumericRangeFilter(Filter): field_class = RangeField
django_filters/__init__.py+1 −1 modified@@ -10,7 +10,7 @@ from . import rest_framework del pkgutil -__version__ = '2.3.0' +__version__ = '2.4.0' def parse_version(version):
docs/conf.py+5 −3 modified@@ -13,6 +13,8 @@ import sys, os +from django_filters import __version__ + # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. @@ -41,16 +43,16 @@ # General information about the project. project = u'django-filter' -copyright = u'2019, Alex Gaynor, Carlton Gibson and others.' +copyright = u'2020, Alex Gaynor, Carlton Gibson and others.' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '2.3' +version = __version__ # The full version, including alpha/beta/rc tags. -release = '2.3.0' +release = __version__ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages.
docs/ref/filters.txt+6 −0 modified@@ -426,6 +426,12 @@ QuerySet, which then gets used as the model's manager:: Filters based on a numerical value, used with ``IntegerField``, ``FloatField``, and ``DecimalField`` by default. +.. method:: NumberFilter.get_max_validator() + + Return a ``MaxValueValidator`` instance that will be added to + ``field.validators``. By default uses a limit value of ``1e50``. Return + ``None`` to disable maximum value validation. + ``NumericRangeFilter`` ~~~~~~~~~~~~~~~~~~~~~~
requirements/maintainer.txt+0 −1 modified@@ -2,7 +2,6 @@ alabaster==0.7.7 argh==0.26.1 Babel==2.2.0 backports.ssl-match-hostname==3.4.0.2 -bumpversion==0.5.3 certifi==2015.9.6.2 docutils==0.12 funcsigs==0.4
setup.py+7 −4 modified@@ -2,12 +2,15 @@ import sys from setuptools import setup, find_packages +# FIXME: Main module requires django to be present, so cannot run setup.py in +# clean environment. +# from django_filters import __version__ +__version__ = '2.4.0' + f = open('README.rst') readme = f.read() f.close() -version = '2.3.0' - if sys.argv[-1] == 'publish': if os.system("pip freeze | grep wheel"): print("wheel not installed.\nUse `pip install wheel`.\nExiting.") @@ -18,13 +21,13 @@ os.system("python setup.py sdist bdist_wheel") os.system("twine upload dist/*") print("You probably want to also tag the version now:") - print(" git tag -a %s -m 'version %s'" % (version, version)) + print(" git tag -a %s -m 'version %s'" % (__version__, __version__)) print(" git push --tags") sys.exit() setup( name='django-filter', - version=version, + version=__version__, description=('Django-filter is a reusable Django application for allowing' ' users to filter querysets dynamically.'), long_description=readme,
tests/test_forms.py+14 −0 modified@@ -255,3 +255,17 @@ def test_is_bound_and_not_valid(self): self.assertFalse(f.is_valid()) self.assertEqual(f.data, {'price': 'four dollars'}) self.assertEqual(f.errors, {'price': ['Enter a number.']}) + + def test_number_filter_max_value_validation(self): + class F(FilterSet): + class Meta: + model = Book + fields = ['average_rating'] + + f = F({'average_rating': '1E1001'}) + self.assertTrue(f.is_bound) + self.assertFalse(f.is_valid()) + self.assertEqual( + f.errors, + {'average_rating': ['Ensure this value is less than or equal to 1e+50.']} + )
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
16- github.com/advisories/GHSA-x7gm-rfgv-w973ghsaADVISORY
- lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/DPHENTRHRAYFXYPPBT7JRHZRWILRY44S/mitrevendor-advisory
- lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/FAT2ZAEF6DM3VFSOHKB7X3ASSHGQHJAK/mitrevendor-advisory
- lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/SVJ7AYU6FUSU3F653YCGW5LFD3IULRSX/mitrevendor-advisory
- nvd.nist.gov/vuln/detail/CVE-2020-15225ghsaADVISORY
- github.com/carltongibson/django-filter/commit/340cf7a23a2b3dcd7183f6a0d6c383e85b130d2bghsaWEB
- github.com/carltongibson/django-filter/releases/tag/2.4.0ghsaWEB
- github.com/carltongibson/django-filter/security/advisories/GHSA-x7gm-rfgv-w973ghsaWEB
- github.com/pypa/advisory-database/tree/main/vulns/django-filter/PYSEC-2021-64.yamlghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/DPHENTRHRAYFXYPPBT7JRHZRWILRY44SghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/FAT2ZAEF6DM3VFSOHKB7X3ASSHGQHJAKghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/SVJ7AYU6FUSU3F653YCGW5LFD3IULRSXghsaWEB
- pypi.org/project/django-filterghsaWEB
- security.netapp.com/advisory/ntap-20210604-0010ghsaWEB
- pypi.org/project/django-filter/mitre
- security.netapp.com/advisory/ntap-20210604-0010/mitre
News mentions
0No linked articles in our index yet.