summaryrefslogtreecommitdiff
path: root/django/core/files/utils.py
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2021-05-13 08:53:44 +0200
committerGitHub <noreply@github.com>2021-05-13 08:53:44 +0200
commitb55699968fc9ee985384c64e37f6cc74a0a23683 (patch)
treeec84729969a2c35777792ef5ca2df54d238391ff /django/core/files/utils.py
parentb81c7562fc33f50166d5120138d6398dc42b13c3 (diff)
downloaddjango-b55699968fc9ee985384c64e37f6cc74a0a23683.tar.gz
Fixed #32718 -- Relaxed file name validation in FileField.
- Validate filename returned by FileField.upload_to() not a filename passed to the FileField.generate_filename() (upload_to() may completely ignored passed filename). - Allow relative paths (without dot segments) in the generated filename. Thanks to Jakub Kleň for the report and review. Thanks to all folks for checking this patch on existing projects. Thanks Florian Apolloner and Markus Holtermann for the discussion and implementation idea. Regression in 0b79eb36915d178aef5c6a7bbce71b1e76d376d3.
Diffstat (limited to 'django/core/files/utils.py')
-rw-r--r--django/core/files/utils.py20
1 files changed, 15 insertions, 5 deletions
diff --git a/django/core/files/utils.py b/django/core/files/utils.py
index f83cb1a3cf..f28cea1077 100644
--- a/django/core/files/utils.py
+++ b/django/core/files/utils.py
@@ -1,16 +1,26 @@
import os
+import pathlib
from django.core.exceptions import SuspiciousFileOperation
-def validate_file_name(name):
- if name != os.path.basename(name):
- raise SuspiciousFileOperation("File name '%s' includes path elements" % name)
-
+def validate_file_name(name, allow_relative_path=False):
# Remove potentially dangerous names
- if name in {'', '.', '..'}:
+ if os.path.basename(name) in {'', '.', '..'}:
raise SuspiciousFileOperation("Could not derive file name from '%s'" % name)
+ if allow_relative_path:
+ # Use PurePosixPath() because this branch is checked only in
+ # FileField.generate_filename() where all file paths are expected to be
+ # Unix style (with forward slashes).
+ path = pathlib.PurePosixPath(name)
+ if path.is_absolute() or '..' in path.parts:
+ raise SuspiciousFileOperation(
+ "Detected path traversal attempt in '%s'" % name
+ )
+ elif name != os.path.basename(name):
+ raise SuspiciousFileOperation("File name '%s' includes path elements" % name)
+
return name