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. The vulnerability affects a significant portion of Django deployments, especially those that build queries dynamically from user input. Django, maintained by the Django Software Foundation, is one of the most widely used Python web frameworks and powers thousands of sites and applications across industries. Developers trust its ORM to protect them from SQL injection, so a flaw in that layer is notable for security teams and developers.
Technical Information
CVE-2025-59681 affects Django's QuerySet.annotate(), alias(), aggregate(), and extra() methods when they run against MySQL or MariaDB. The problem appears when a dictionary is passed as **kwargs to these methods. Django's ORM uses the dictionary keys directly as column aliases in the generated SQL, and on MySQL and MariaDB those aliases allow SQL injection if the keys are not properly sanitized.
The root cause is that Django did not validate dictionary keys used as column aliases. If user-controlled input can influence those keys, an attacker can craft a dictionary whose key contains malicious SQL. Django then inserts that key into the query as an alias, outside its usual parameterization and escaping. The issue is specific to MySQL and MariaDB because of their SQL syntax and the way they parse column aliases.
For example, if an application builds a dictionary from user input and passes it as **kwargs to annotate(), an attacker could supply a key like malicious_alias; DROP TABLE users; -- and have it inserted into the SQL query. Depending on the database user's privileges, that could let the attacker run arbitrary SQL statements, exfiltrate data, or destroy it. Other backends, such as PostgreSQL and SQLite, are not affected.
No public code snippets or PoC are available as of this writing. 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 fix two security vulnerabilities:
-
CVE-2025-59681: A high-severity issue involving potential SQL injection in the
QuerySet.annotate(),alias(),aggregate(), andextra()methods on MySQL and MariaDB databases. Column aliases allowed SQL injection when a specially crafted dictionary was passed as**kwargsto these methods.The patch adds validation so that column aliases provided via
**kwargsare properly sanitized, which stops malicious input from being executed as SQL code. -
CVE-2025-59682: A low-severity partial directory-traversal vulnerability in the
django.utils.archive.extract()function, whichstartapp --templateandstartproject --templateuse. The function allowed partial directory traversal through an archive containing file paths with a common prefix matching the target directory.The patch makes the
extract()function validate and sanitize file paths inside archives, so extracted files cannot escape the intended target directory.
The fixes have been applied to Django's main, 6.0 (currently in alpha), 5.2, 5.1, and 4.2 branches. Users are strongly encouraged to upgrade to the latest versions.
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 that use MySQL or MariaDB as the database backend are affected. Other backends are not vulnerable to this issue.
Vendor Security History
Django has a strong security track record, but 2025 has brought 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 these disclosures, with coordinated patches and advisories for all supported versions. The project's security process is mature and transparent, with clear communication and fast fixes.



