summaryrefslogtreecommitdiff
path: root/django/db/models/sql/query.py
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2022-04-01 13:48:47 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-04-11 09:23:12 +0200
commit29a6c98b4c13af82064f993f0acc6e8fafa4d3f5 (patch)
treec4887e5e3288a71981a457b7f4376ae0c2e45435 /django/db/models/sql/query.py
parent2c09e68ec911919360d5f8502cefc312f9e03c5d (diff)
[2.2.x] Fixed CVE-2022-28347 -- Protected QuerySet.explain(**options) against SQL injection on PostgreSQL.
Backport of 6723a26e59b0b5429a0c5873941e01a2e1bdbb81 from main.
Diffstat (limited to 'django/db/models/sql/query.py')
-rw-r--r--django/db/models/sql/query.py10
1 files changed, 10 insertions, 0 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 412e817f10..1e823cfe74 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -45,6 +45,10 @@ __all__ = ['Query', 'RawQuery']
# SQL comments are forbidden in column aliases.
FORBIDDEN_ALIAS_PATTERN = re.compile(r"['`\"\]\[;\s]|--|/\*|\*/")
+# Inspired from
+# https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
+EXPLAIN_OPTIONS_PATTERN = re.compile(r"[\w\-]+")
+
def get_field_names_from_opts(opts):
return set(chain.from_iterable(
@@ -528,6 +532,12 @@ class Query:
def explain(self, using, format=None, **options):
q = self.clone()
+ for option_name in options:
+ if (
+ not EXPLAIN_OPTIONS_PATTERN.fullmatch(option_name) or
+ "--" in option_name
+ ):
+ raise ValueError("Invalid option name: '%s'." % option_name)
q.explain_query = True
q.explain_format = format
q.explain_options = options