Problem/Motivation

My concern is to use the ability provided by $settings['file_public_path'] and $settings['file_public_base_url'] to
provide a separate webserver dedicated to serve static files and user content. For security, this web server has
deliberately no PHP support.

To facilitate the debug of this issue, I created a simple docker-project hosted on Github:
https://github.com/mickaelperrin/drupal-issues/tree/2754273-image_styles...

Steps to reproduce using the docker container:

1. Launch the docker container with docker-compose up -d`
2. Go to http://your.docker.machine.ip:8888
3. Authenticate with drupal / drupal
4. Go to http://your.docker.machine.ip:8888/node/add/article
5. Click on the "Add image" button
6. Select a file

Exepected result: The thumbnail of the selected image is properly displayed

Result: The thumbnail show a missing image (error 404)`

Proposed resolution

The problem seems to be related with the `PathProcessor`of the module `image`. It appends at the beggining of the
public setting path a slash wether the path is absolute or relative.

In case of absolute path, two slashs begin the path and the method to detect if the path is public or private fails, and
so on the url processing.

The attached add a simple test to check if a slash is needed or not.

You can test the issue with the path by launching the docker containers with the command: `docker-compose -f docker-compose.yml -f docker-compose.patched.yml up -d`

Remaining tasks

As it is my first patch and I am new to Drupal, a review is obviously needed.

Issue fork drupal-2754273

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mickaelperrin created an issue. See original summary.

mickaelperrin’s picture

Issue summary: View changes
StatusFileSize
new1.02 KB
mickaelperrin’s picture

Assigned: mickaelperrin » Unassigned
Status: Needs work » Needs review

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

klausi’s picture

Priority: Normal » Major
Issue tags: +Needs tests
StatusFileSize
new3.17 KB

I think the patch is not fully correct. Instead of using the path from $settings['file_public_path'] we should use the path from $settings['file_public_base_url'].

This is necessary for sites that want to run Drupal in a secure fashion with an isolated web root. They have to set

$settings['file_public_path'] = 'web/files';
$settings['file_public_base_url'] = 'https://klau.si/files';

for example. As this is an important security improvement and this breaks image styles on such sites I think this should be major.

Here is a new patch that uses $settings['file_public_base_url'] if set.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

bsztreha’s picture

I can successfully apply #7 patch to Drupal 8.6.16, and seems working.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

twilderan’s picture

Patch from #7 works for me on Drupal 8.9.6, both Media and regular images.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

jibran’s picture

Now that #3036494: Race condition in ImageStyle::createDerivative() is committed can we try to reproduce this?

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

richard.walker.ardc’s picture

StatusFileSize
new3.25 KB

Attached re-rolled patch.

richard.walker.ardc’s picture

A note about configuration that works, and what doesn't work.

What does work #1: where the Drupal base URL doesn't end with a subpath, and file_public_base_url ends with a subpath. For example, Drupal installed as https://myhost, and file_public_base_url as https://myhost/files.

What does work #2: where the Drupal base URL ends with a subpath, and file_public_base_url ends with a different subpath. For example, Drupal installed as https://myhost/drupalpath, and file_public_base_url as https://myhost/drupalpathfiles.

What doesn't work: where the Drupal base URL ends with a subpath, and file_public_base_url ends with a subpath of the Drupal base supbath. For example, Drupal installed as https://myhost/drupalpath, and file_public_base_url as https://myhost/drupalpath/files. Here's what seems to be the reason: in this case, the image.style_public route is set up with path /drupalpath/files/styles/..., but since REQUEST_URI also begins /drupalpath/files/styles/... and Drupal's base path ends /drupalpath, Symfony strips the leading /drupalpath element from the REQUEST_URI and looks for a route /files/styles/... instead ... but there isn't one.

richard.walker.ardc’s picture

And (of course?) if file_public_path points to an absolute path that's outside Drupal, that directory needs to have its .htaccess rewrite to Drupal in the case of a miss.

The existing, generated .htaccess has:

# Turn off all options we don't need.
Options -Indexes -ExecCGI -Includes -MultiViews

# Set the catch-all handler to prevent scripts from being executed.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<Files *>
  # Override the handler again if we're run later in the evaluation list.
  SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
</Files>

# If we know how to do it safely, disable the PHP engine entirely.
<IfModule mod_php7.c>
  php_flag engine off
</IfModule>

I inserted this (copy/pasted from Drupal's own .htaccess) at the top (where, as per my previous comment, my Drupal is installed at /drupalpath):

RewriteEngine on
# Make sure Authorization HTTP header is available to PHP
# even when running as CGI or FastCGI.
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ /drupalpath/index.php [L]

Any problems with this? (I'm not sure if I need the line for authorization, and I'm reasonably sure I don't need the line for favicon.ico.)

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

richard.walker.ardc’s picture

A follow-up to something I wrote earlier:

What does work #2: where the Drupal base URL ends with a subpath, and file_public_base_url ends with a different subpath. For example, Drupal installed as https://myhost/drupalpath, and file_public_base_url as https://myhost/drupalpathfiles.

It turns out that although this example works for thumbnail generation, it breaks file download URLs. In fact, in this example, note that the base URL is not "different" enough, it's now a prefix of the file_public_base_url. To make file download URLs work, the example must be changed to, e.g., https://myhost/filesdrupalpath.

See core/lib/Drupal/Component/Utility/UrlHelper.php's function externalIsLocal(), as invoked by core/modules/file/FileUrlGenerator.php's function generate().

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

vladimiraus’s picture

StatusFileSize
new3.28 KB

Status: Needs review » Needs work

The last submitted patch, 25: drupal-image_styles-2754273-25.patch, failed testing. View results

vladimiraus’s picture

Issue summary: View changes

Moved to merge request.

vladimiraus’s picture

Status: Needs work » Needs review
fago’s picture

Status: Needs review » Needs work

Thank you, I took a look at the MR and left a couple of comments, see above. Also, the MR should fixed to point against 10.1.x to match the issue version.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

vladimiraus’s picture

Use 9.5 MR for Drupal 10.0.

manarth’s picture

brad.bulger’s picture

Is this testing relative paths that resolve outside of the Drupal webroot? For example, I've been testing a setup where Drupal is installed in a subdirectory on the server, using $settings['file_public_path'] = '../public';. So a Drupal page would be https://my.server/path/to/drupal/web/node/1 and an uploaded image would be https://my.server/path/to/drupal/public/image01.png. That doesn't work with image styles, so I tried setting file_public_base_url to 'https://my.server/path/to/drupal/public'. That has many of the same symptoms described here.

Is adding the clean URL redirect lines to the public file folder .htaccess file going to be a requirement in any case? In order to do things like process the virtual URLs of image styles, for instance.

VladimirAus changed the visibility of the branch 10.1.x to hidden.

vladimiraus’s picture

Version: 11.x-dev » 11.0.x-dev
Status: Needs work » Needs review

VladimirAus changed the visibility of the branch 2754273-10.1.x-image-styles-fails to hidden.

VladimirAus changed the visibility of the branch 11.0.x to hidden.

suryabhi’s picture

StatusFileSize
new3.25 KB

Reroll the patch

smustgrave’s picture

Status: Needs review » Needs work

Can MR be updated to 11.x please

have not reviewed for tests yet

socialnicheguru’s picture

is there a MR for Drupal 10.3?

vladimiraus’s picture

@SocialNicheGuru current MR's diff is working for 10.3.

vladimiraus’s picture

Version: 11.0.x-dev » 11.x-dev
Status: Needs work » Needs review

@smustgrave done

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new90 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

vladimiraus’s picture

Status: Needs work » Needs review

Should be good now and pass phpcs

smustgrave’s picture

Status: Needs review » Needs work

Thanks! Appears to still need tests though.

heatherwoz’s picture

StatusFileSize
new3.37 KB

Posting the latest diff as a patch.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.