Skip to content

Allow absolute filesystem paths in ImageField::setUploadDir() #7459

@redeye86

Description

@redeye86

Currently, ImageField::setUploadDir() only supports paths relative to kernel.project_dir.

Internally, the upload directory is normalized like this:

$relativeUploadDir = u($relativeUploadDir)
    ->trimStart(\DIRECTORY_SEPARATOR)
    ->ensureEnd(\DIRECTORY_SEPARATOR)
    ->toString();

$isStreamWrapper = filter_var($relativeUploadDir, \FILTER_VALIDATE_URL);

if (false !== $isStreamWrapper) {
    $absoluteUploadDir = $relativeUploadDir;
} else {
    $absoluteUploadDir = u($relativeUploadDir)
        ->ensureStart($this->projectDir.\DIRECTORY_SEPARATOR)
        ->toString();
}

Because of trimStart(DIRECTORY_SEPARATOR), it is currently impossible to pass a true absolute path like:
/mnt/data/article-assets

The only workaround is using:

relative ../../.. constructs
or use file:// to trick the uploader to use stream wrappers

Both are technically working but unintuitive and not officially documented.

Why this is problematic

  • Many production setups store uploads outside of kernel.project_dir.
  • Using ../ chains is fragile and unclear.
  • Using file:// works but relies on URL detection instead of explicit filesystem support.
  • The current behavior is surprising because setUploadDir() suggests a directory path, not necessarily a project-relative path.

Suggested improvement

Allow true absolute filesystem paths by detecting them explicitly:

if (str_starts_with($relativeUploadDir, DIRECTORY_SEPARATOR)) {
    $absoluteUploadDir = $relativeUploadDir;
} elseif (false !== filter_var($relativeUploadDir, FILTER_VALIDATE_URL)) {
    $absoluteUploadDir = $relativeUploadDir;
} else {
    $absoluteUploadDir = $this->projectDir . DIRECTORY_SEPARATOR . $relativeUploadDir;
}

Even if the original intention was to prevent the user from uploading data to a system directory, this would be still possible using the current implementation by prepending file:// or a bunch of "../" to the path. But I think that is a problem that is out of scope anyway. Changing system files should not be possible due to permissions and the devs should not use user-generated paths without sanitazing anyway (if at all).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions