diff options
| author | YashRaj1506 <yashraj504300@gmail.com> | 2025-06-26 03:31:00 +0530 |
|---|---|---|
| committer | nessita <124304+nessita@users.noreply.github.com> | 2025-10-20 16:21:32 -0300 |
| commit | 9bb83925d6c231e964f8b54efbc982fb1333da27 (patch) | |
| tree | bbf430620cdb633c587414ef9a4910812aa148d7 /django/utils | |
| parent | 5625bd590766e5ca8c2c76ba2307b98f7450ff83 (diff) | |
Fixed #36470 -- Prevented log injection in runserver when handling NOT FOUND.
Migrated `WSGIRequestHandler.log_message()` to use a more robust
`log_message()` helper, which was based of `log_response()` via factoring out
the common bits.
Refs CVE-2025-48432.
Co-authored-by: Natalia <124304+nessita@users.noreply.github.com>
Diffstat (limited to 'django/utils')
| -rw-r--r-- | django/utils/log.py | 67 |
1 files changed, 47 insertions, 20 deletions
diff --git a/django/utils/log.py b/django/utils/log.py index 67a40270f0..d4e96a9816 100644 --- a/django/utils/log.py +++ b/django/utils/log.py @@ -214,6 +214,46 @@ class ServerFormatter(logging.Formatter): return self._fmt.find("{server_time}") >= 0 +def log_message( + logger, + message, + *args, + level=None, + status_code=None, + request=None, + exception=None, + **extra, +): + """Log `message` using `logger` based on `status_code` and logger `level`. + + Pass `request`, `status_code` (if defined) and any provided `extra` as such + to the logging method, + + Arguments from `args` will be escaped to avoid potential log injections. + + """ + extra = {"request": request, **extra} + if status_code is not None: + extra["status_code"] = status_code + if level is None: + if status_code >= 500: + level = "error" + elif status_code >= 400: + level = "warning" + + escaped_args = tuple( + a.encode("unicode_escape").decode("ascii") if isinstance(a, str) else a + for a in args + ) + + getattr(logger, level or "info")( + message, + *escaped_args, + extra=extra, + exc_info=exception, + ) + + def log_response( message, *args, @@ -237,26 +277,13 @@ def log_response( if getattr(response, "_has_been_logged", False): return - if level is None: - if response.status_code >= 500: - level = "error" - elif response.status_code >= 400: - level = "warning" - else: - level = "info" - - escaped_args = tuple( - a.encode("unicode_escape").decode("ascii") if isinstance(a, str) else a - for a in args - ) - - getattr(logger, level)( + log_message( + logger, message, - *escaped_args, - extra={ - "status_code": response.status_code, - "request": request, - }, - exc_info=exception, + *args, + level=level, + status_code=response.status_code, + request=request, + exception=exception, ) response._has_been_logged = True |
