Skip to content

Fast 404 answers missing image style derivatives with a 404 for every user, so they're never generated #3211

Closed

Description

@AlexSkrypnyk

Summary

web/sites/default/includes/modules/settings.fast_404.php sets fast404_allow_anon_imagecache to FALSE. With drupal/fast_404 3.7.0, that answers every request for a missing public png, gif or jpg image style derivative with the fast 404, for anonymous and logged-in users alike. Drupal only generates a derivative when its URL is first requested, so on a site with this setting derivatives are never generated: newly uploaded images, new image styles and everything after an image style flush render broken.

1.42.0 is the first release where this applies. #3101 fixed the settings guard and started shipping drupal/fast_404 (on by default in new installs; existing projects get it only when they require the package), and #3102 set the value to FALSE. In 1.41.1 the guard checked a path Composer never creates, so the handler never ran.

Details

Cause

For a path that contains styles/, Fast404::extensionCheck() is meant to let logged-in users through when it finds a session cookie:

$cookies = $this->request->cookies->all();

// At this stage of the game we don't know if the user is logged in via
// regular function calls. Simply look for a session cookie. If we find
// one we'll assume they're logged in.
if (isset($cookies) && is_array($cookies)) {
  foreach ($cookies as $cookie) {
    if (stristr($cookie, 'SESS')) {
      return;
    }
  }
}

cookies->all() returns cookie names mapped to values, and the loop only looks at the values. Drupal puts SESS in the cookie name (SESS<hash>, or SSESS<hash> over HTTPS), while the value is a random session ID, so the exception never matches. The request falls through to the fast404_exts check, which matches .png, .gif and .jpg.

Private files under /system/files and WebP-converted styles aren't affected, because the extension pattern doesn't match them.

Reproduction

Running the module's Fast404 class with the shipped settings against /sites/default/files/styles/large/public/2026-10/photo.jpg, once with no cookies and once with a SSESS<hash> session cookie:

fast404_allow_anon_imagecache Anonymous Logged in
FALSE blocked (404) blocked (404)
TRUE passed to Drupal passed to Drupal

Fast404::isPathBlocked() always returns FALSE under the CLI SAPI, so a command-line check has to read the respond404 property instead. On a provisioned site, upload an image, then request one of its derivative URLs logged out and logged in.

subtestAhoyFast404() in .vortex/tests doesn't catch this, because it requests a derivative of a source image that doesn't exist, which returns a 404 either way.

Fix options

  • Set fast404_allow_anon_imagecache to TRUE, the module default and the value its README shows. Missing derivatives then reach Drupal, which already rejects derivative URLs without a valid itok token by default. The change also needs the 17 expectations in tests/phpunit/Drupal/EnvironmentSettingsTest.php and tests/phpunit/Drupal/SwitchableSettingsTest.php, the derivative assertions in subtestAhoyFast404(), and the Fast 404 settings list in .vortex/docs/content/development/modules/contributed-modules.mdx, followed by ahoy update-snapshots.
  • Keep FALSE and patch the module to match SESS against cookie names. Logged-in users could then generate derivatives, but anonymous visitors would still get broken images for any derivative that nobody logged in has triggered yet.

Activity

  1. added a commit that references this issue on Oct 20, 2026
  2. moved this from BACKLOG to Release queue in Vortex 1.xon Oct 20, 2026
  3. added this to the 1.42.0 milestone on Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A4Board worker 4

    Type

    No type

    Projects

    • Status
      Released in 1.42.0

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions