Django CVE-2025-59681: Brief Summary of a High-Severity SQL Injection Vulnerability in QuerySet Methods

This post provides a brief summary of CVE-2025-59681, a high-severity SQL injection vulnerability affecting Django's QuerySet methods on MySQL and MariaDB. It covers affected versions, technical details, and official patch information.
CVE Analysis

9 min read

ZeroPath CVE Analysis

ZeroPath CVE Analysis

2025-10-01

Django CVE-2025-59681: Brief Summary of a High-Severity SQL Injection Vulnerability in QuerySet Methods
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

Attackers who can control dictionary keys passed to certain Django QuerySet methods may be able to execute arbitrary SQL on MySQL or MariaDB backends. This vulnerability affects a significant portion of Django deployments, especially those using dynamic query construction with user input. The Django web framework, maintained by the Django Software Foundation, is a cornerstone of Python web development and powers thousands of sites and applications across industries. Its ORM layer is trusted for strong SQL injection protections, making this vulnerability particularly notable for security teams and developers.

Technical Information

CVE-2025-59681 targets Django's QuerySet.annotate(), alias(), aggregate(), and extra() methods when used with MySQL or MariaDB databases. The vulnerability arises when a dictionary is passed as **kwargs to these methods. In Django's ORM, these dictionary keys are used directly as column aliases in the generated SQL. On MySQL and MariaDB, the handling of these aliases allows for SQL injection if the keys are not properly sanitized.

The root cause is the lack of validation on dictionary keys used as column aliases. When user-controlled input is allowed to influence these keys, an attacker can craft a dictionary where the key contains malicious SQL. This key is then inserted into the SQL query as an alias, bypassing Django's usual parameterization and escaping mechanisms. The vulnerability is specific to MySQL and MariaDB due to their SQL syntax and how they parse column aliases.

For example, if an application constructs a dictionary from user input and passes it as **kwargs to annotate(), an attacker could supply a key like malicious_alias; DROP TABLE users; -- which would be inserted into the SQL query. This could allow for execution of arbitrary SQL statements, data exfiltration, or destruction, depending on the database user's privileges. The vulnerability does not affect other backends such as PostgreSQL or SQLite.

No public code snippets or PoC are available as of this writing, and exploitation requires that user input is used directly as dictionary keys in these methods.

Patch Information

The Django team has released versions 5.2.7, 5.1.13, and 4.2.25 to address two security vulnerabilities:

  1. CVE-2025-59681: This high-severity issue involved potential SQL injection vulnerabilities in the QuerySet.annotate(), alias(), aggregate(), and extra() methods on MySQL and MariaDB databases. The vulnerability allowed SQL injection through column aliases when a specially crafted dictionary was passed as **kwargs to these methods.

    Patch Details:

    • The patch introduces validation to ensure that column aliases provided via **kwargs are properly sanitized, preventing malicious input from being executed as SQL code.
  2. CVE-2025-59682: This low-severity issue pertained to a partial directory-traversal vulnerability in the django.utils.archive.extract() function. The function, used by startapp --template and startproject --template, allowed partial directory traversal via an archive containing file paths with a common prefix matching the target directory.

    Patch Details:

    • The patch enhances the extract() function to validate and sanitize file paths within archives, ensuring that extracted files do not escape the intended target directory.

These patches have been applied to Django's main, 6.0 (currently at alpha status), 5.2, 5.1, and 4.2 branches. Users are strongly encouraged to upgrade to the latest versions to mitigate these vulnerabilities.

Patch source: https://www.djangoproject.com/weblog/2025/oct/01/security-releases/

Affected Systems and Versions

  • Django 4.2 before 4.2.25
  • Django 5.1 before 5.1.13
  • Django 5.2 before 5.2.7

Only installations using MySQL or MariaDB as the database backend are affected. Other database backends are not vulnerable to this issue.

Vendor Security History

Django has a strong security track record, but 2025 has seen several notable vulnerabilities in its ORM layer. CVE-2025-57833, disclosed in September 2025, affected the FilteredRelation feature and also allowed SQL injection under certain conditions. The Django team has consistently responded quickly to such disclosures, issuing coordinated patches and advisories for all supported versions. The project maintains a transparent and mature security process, with clear communication and rapid remediation.

References

Detect & fix
what others miss