django/django · warning · SuspiciousFileOperation

File name '%s' includes path elements

Error message

File name '%s' includes path elements

What it means

Raised as a django.core.exceptions.SuspiciousFileOperation by validate_file_name() (the default code path, allow_relative_path=False) when the given name is not equal to its own basename — i.e. it contains '/', '\', or other path separators. Django requires file names to be bare names so the storage backend can place them safely; any embedded path is rejected.

Source

Thrown at django/core/files/utils.py:21

from django.core.exceptions import SuspiciousFileOperation


def validate_file_name(name, allow_relative_path=False):
    # Remove potentially dangerous names
    if os.path.basename(name) in {"", ".", ".."}:
        raise SuspiciousFileOperation("Could not derive file name from '%s'" % name)

    if allow_relative_path:
        # Ensure that name can be treated as a pure posix path, i.e. Unix
        # style (with forward slashes).
        path = pathlib.PurePosixPath(str(name).replace("\\", "/"))
        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


class FileProxyMixin:
    """
    A mixin class used to forward file methods to an underlying file
    object. The internal file object has to be called "file"::

        class FileProxy(FileProxyMixin):
            def __init__(self, file):
                self.file = file
    """

    encoding = property(lambda self: self.file.encoding)
    fileno = property(lambda self: self.file.fileno)
    flush = property(lambda self: self.file.flush)
    isatty = property(lambda self: self.file.isatty)

View on GitHub (pinned to ae25a40be0)

Solutions

  1. Flatten the name to its basename: name = os.path.basename(name) before calling save().
  2. If you need subdirectories, use a storage backend/path that supports it and pass allow_relative_path=True only after sanitizing (see error 400).
  3. Construct flat, unique names yourself, e.g. name = f'{uuid4().hex}.pdf'.

Example fix

// before
storage.save(os.path.join('uploads', upload.name), content)
// after
storage.save(os.path.basename(upload.name), content)
Defensive patterns

Strategy: validation

Validate before calling

import os
def flat_name(name):
    base = os.path.basename(str(name).replace('\\', '/'))
    if base in ('', '.', '..'):
        raise ValueError(f'cannot derive a flat name from {name!r}')
    return base

Type guard

import os
def is_flat_filename(name: str) -> bool:
    return name == os.path.basename(str(name).replace('\\', '/'))

Try / catch

from django.core.exceptions import SuspiciousFileOperation
try:
    storage.save(name, content)
except SuspiciousFileOperation:
    storage.save(os.path.basename(name), content)

Prevention

When it happens

Trigger: Calling storage.save('subdir/file.txt', content) or FieldFile.save with a name containing a slash; passing a full Windows path like 'C:\\tmp\\f.txt'; assigning a model FileField a value containing directory separators.

Common situations: Saving uploads preserving the original browser sub-path; generating names with os.path.join('user_1', 'doc.pdf') instead of a flat name; copying paths from an external source into storage.save.

Related errors


AI-assisted analysis of django/django@ae25a40be0 (2026-08-06). Data as JSON: /api/errors/fc7bc26fdb443c77. Report an issue: GitHub.