Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-15830

CVE-2026-15830: Django GeoDjango DoS Vulnerability

CVE-2026-15830 is a denial-of-service vulnerability in Django's GeoDjango component that triggers unbounded recursion when parsing nested GEOMETRYCOLLECTION objects. This article covers technical details, affected versions, and mitigation.

Published:

CVE-2026-15830 Overview

CVE-2026-15830 is a denial-of-service vulnerability in Django's GeoDjango component. The flaw affects Django 5.2 before 5.2.17 and 6.0 before 6.0.8. GeoDjango's django.contrib.gis.geos.GEOSGeometry fails to bound recursion when parsing deeply nested GEOMETRYCOLLECTION objects. Attackers can submit crafted well-known text (WKT), well-known binary (WKB), or hex-encoded WKB payloads to trigger unbounded recursion and a segmentation fault in the underlying GEOS library. Spatial field lookups and the django.contrib.gis.forms.GeometryField form field carry the same exposure. Earlier unsupported Django series (5.1.x, 5.0.x, and 4.2.x) were not evaluated and may also be affected. The issue is tracked as [CWE-674] Uncontrolled Recursion.

Critical Impact

Unauthenticated remote attackers can crash Django worker processes by submitting deeply nested GEOMETRYCOLLECTION payloads to any spatial input, resulting in service unavailability.

Affected Products

  • Django 5.2 before 5.2.17
  • Django 6.0 before 6.0.8
  • Earlier unsupported series (5.1.x, 5.0.x, 4.2.x) not evaluated and potentially affected

Discovery Timeline

  • Vulnerability reported by Andrew MacPherson and kimchunbok_
  • 2026-08-04 - Django releases security patches (versions 5.2.17 and 6.0.8)
  • 2026-08-04 - CVE-2026-15830 published to NVD
  • 2026-08-04 - Last updated in NVD database

Technical Details for CVE-2026-15830

Vulnerability Analysis

GeoDjango wraps the C-based GEOS library through GEOSGeometry and its base class GEOSGeometryBase. When Django parses a GEOMETRYCOLLECTION, the underlying GEOS parser recursively descends into each nested geometry element without enforcing a nesting depth cap. An attacker who submits a WKT, WKB, or hex-WKB payload containing thousands of nested collections forces the parser to exhaust the call stack. The result is a segmentation fault inside the shared library, which terminates the Django worker process.

Any surface that accepts user-supplied geometry data is a viable entry point. This includes spatial field lookups in ORM queries and the django.contrib.gis.forms.GeometryField form field bound to user input. Because parsing occurs before validation, standard form-level constraints do not stop the crash.

Root Cause

The root cause is uncontrolled recursion [CWE-674] in the GEOS geometry reader. Django did not pass a bound for the maximum number of nested collections through to the reader, so recursion continued until the operating system killed the process on stack overflow.

Attack Vector

An unauthenticated remote attacker sends a single HTTP request containing a crafted GEOMETRYCOLLECTION value to any endpoint that binds the value into a GeometryField, a spatial lookup, or a queryset filter. Parsing triggers the segmentation fault and terminates the worker. Repeated requests from a single source can keep worker capacity depleted, producing a sustained outage.

python
# Django patch (excerpt) - django/contrib/gis/db/backends/mysql/operations.py
# The fix threads a max_geom_collections argument through the reader.
def converter(value, expression, connection):
    if value is not None:
        geom = GEOSGeometryBase(
            read(memoryview(value), max_geom_collections=None), geom_class
        )
        if srid:
            geom.srid = srid
        return geom
# Source: https://github.com/django/django/commit/ba80833fa656dd09660b97c4429331067db1b080

Detection Methods for CVE-2026-15830

Indicators of Compromise

  • Repeated segmentation faults or abnormal terminations of Python worker processes (gunicorn, uWSGI, Daphne) handling GeoDjango requests.
  • HTTP request bodies or query parameters containing unusually long strings of nested GEOMETRYCOLLECTION( tokens or repeated hex-WKB collection type codes (0x07).
  • Sudden spikes in HTTP 502 or 504 responses from endpoints backed by django.contrib.gis views.

Detection Strategies

  • Inspect WAF or reverse proxy logs for payloads containing more than a small threshold of GEOMETRYCOLLECTION occurrences in a single field.
  • Correlate worker restarts with request identifiers to identify the offending client IP and payload signature.
  • Monitor GEOS-linked processes for SIGSEGV exits using host telemetry and container runtime signals.

Monitoring Recommendations

  • Alert on any process crash for Django workers serving /gis/, spatial API routes, or endpoints accepting geometry input.
  • Track request size and structural complexity for parameters bound to GeometryField inputs.
  • Log GEOS library errors and application-level 500 responses from spatial views for post-incident review.

How to Mitigate CVE-2026-15830

Immediate Actions Required

  • Upgrade Django to version 5.2.17 or 6.0.8 on all instances running django.contrib.gis.
  • Audit unsupported Django deployments (5.1.x, 5.0.x, 4.2.x) and plan migration, since these series were not evaluated for this issue.
  • Enforce request body size limits and reject payloads with excessive nesting at the reverse proxy or WAF layer.

Patch Information

Django released fixes on 2026-08-04. The patches thread a max_geom_collections parameter through GEOS readers to bound recursion during geometry parsing. See Django Weblog Security Releases, the Django Security Release Notes, and commits ba80833 (5.2.x), 6af5da3 (6.0.x), 9e4a3f1 (6.1.x), and d2e59b7.

Workarounds

  • Restrict maximum request body size for endpoints accepting spatial input at the load balancer or WAF.
  • Add a WAF rule that rejects requests containing more than a safe threshold of GEOMETRYCOLLECTION tokens or nested \\x07 type codes.
  • Require authentication on all endpoints that bind geometry data until patching completes.
bash
# Example: pin patched Django versions in requirements
pip install "Django>=5.2.17,<5.3"
# or for the 6.0 series
pip install "Django>=6.0.8,<6.1"

# Verify installed version
python -c "import django; print(django.get_version())"

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.