• Resolved Alexander Guskov

    (@forcesail)


    I have noted that sometimes some pages that are in the list “URLs to exclude from caching” comes from browser cache (Chrome 109).

    I spent a few days to investigate the problem and found:
    1) When WPO is deactivated all comes (to pages) from wp_include/function.php (wp_get_nocache_headers)
    Cache-Control: no-cache, must-revalidate, max-age=0
    Expires: Wed, 11 Jan 1984 05:00:00 GMT

    That is neutral to caching (no cache but is not secure from storing some cache is browser)

    2) When WPO is just activated but any caching is off it adds cache-control: private, must-revalidate to .htaccess file (it seams that mod_headers.c replace only the records that have been added by it) and since that all pages have 2 cache-control records in their headers (another cache-control: no-cache, must-revalidate, max-age=0 comes from WP core (see #1)), that according to Apache documentation “can lead to unforeseen consequences”(https://httpd.apache.org/docs/2.4/mod/mod_headers.html#header)
    So, when WPO is just activated it already create the problem!

    3) When WPO is active and caching it adds cache-control: no-cache that replace that one, that comes from WP core (see #1) but with that one, that comes from .htaccess are still creates 2 cache-control records in header.

    4) But the real problem happens with pages that marked to be excluded from caching. Including them in the list “URLs to exclude from caching” we clear understand that we are doing our best to avoid them to be cached. So we expect to find in the header something like:
    cache-control: no-cache, no-store, max-age=0
    and no expires record
    But there are:
    cache-control: private, must-revalidate (comes from .htaccess file (see #2)
    expares: in future

    It means that such pages are stored by browser and can be shown later and even to someone else.

    It definitely should be added “no-store” to Cache-Control (as well as no-cache, max-age=0 and expires should be removed for such “exclude from cache” pages to prevent known leak of security (one of them described by chrome team here: https://github.com/fergald/explainer-bfcache-ccns/blob/main/README.md )

    I know that the question either use “no-store” or not is discussable and on https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching baselessly climes not to use it, but all real browser use it as it assumed can be used
    https://web.dev/http-cache/#cache-control

    5) A bit more errors with “URLs to exclude from caching”:
    I input there:
    =========
    /tests/*
    /yandexinfo.php
    /regsem/*
    ========
    where /regsem/ is a page and it doesn’t cache,
    /yandexinfo.php is a page and it doesn’t cache,
    BUT /tests/* is the 1st level of structure and it caches (but the next levels are not.
    https://forcesail.ru/tests/ (cached)
    https://forcesail.ru/tests/basic-movements/ (not cached)

    6) It’s probably incorrect that you WPO ignores nocache_headers WP core hook to synchronize header’s recording with WP and other plugin and adds headers directly. I haven’t investigated that it comes to any errors now but it’s breaking of structure and is a posible way to serious problems in any future.

Viewing 15 replies - 1 through 15 (of 25 total)
  • Plugin Contributor Venkat Raj

    (@webulous)

    @forcesail I was unable to reproduce the two cache-control headers issue. Here is what I done.

    When a user is logged in, the header cache-control: no-cache, must-revalidate, max-age=0 comes from WP core

    When WP-O is active and cache is off, but the browser cache is enabled, Dashboard => WP-Optimize => Cache => Static file headers it adds cache-control: private, must-revalidate from .htaccessfile which you can avoid by disabling browser caching.

    But still I can’t reproduce the double header issue. I tested in Chrome Version 114.0.5735.90 (Official Build) (64-bit) on Linux desktop

    Thread Starter Alexander Guskov

    (@forcesail)

    Hello,
    I investigated the issue with my site and some others that use WPO (that ones that mentioned in support) and found:
    1) this is common Apache behavior (that goes against the documentation) of the modules mod_expires.c and mod_headers.c:
    1.1) if “Expires” record doesn’t exists in the header mod_expires.c creates (it’s correct) but ALWAYS it own header “Cache-Control” record
    1.2) mod_headers.c with directive ‘Header set Cache-Control “acts almost like “Header add”: it adds another header “Cache-Control” record but replace the record, created by mod_expires.c .
    If to add “early” to ‘Header set Cache-Control ” mod_headers.c creates header record before php and php replace it but mod_expires.c creates it own record anyway.
    IF ‘Header merge Cache-Control ” it merge with the record that made by mod_expires.c but not with one made by php.
    And so on….
    I can share a table of results of the experiments (more than 30 ones) with screenshots of proofs with you.

    I just remain that some browsers see just one of 2 similar records in header (the 1st or the 2nd) and some see 2, but it’s not crear witch one they accept.

    So, it’s seems that the only way to make it working on all http servers – to generate this records from php only.

    4) For pages that in the list of exception from caching strictly should be “Cache-Control=no-store”

    5) It’s just wrong interpretation of the mask in the list of exceptions.

    Plugin Support vupdraft

    (@vupdraft)

    Hi,

    Could you share your results, could you also write me some step by step instructions on how to recreate the issue?

    Thread Starter Alexander Guskov

    (@forcesail)

    Hello,

    of course I can. Can I do it by email?

    Plugin Support vupdraft

    (@vupdraft)

    Unfortunately we are not allowed to ask for information via email (WP regulations, not ours).

    You can use something like We Transfer though

    Thread Starter Alexander Guskov

    (@forcesail)

    Enjoy it ??
    Hyperlinks to screenshots-proofs works.
    https://forcesail.ru/Cache-Control/cc.html
    Especially made it for you. :))
    All experiments with “unloged-in” user were made in incogtito mode.

    I tried so other browsers and analyzers. Most of them see only one of the Cache-control records: #1 or #2.

    What it should be:
    1) single cache-control record in the header (so, it seams that mod_headers.c and mod_expires.c doesn’t work properly in Apache)
    2) Independently is WHO active or nor, is WPO cache on or off, for all php/html it should be:
    Cache-control = “no-cache, private”
    no-cache – to force browser to check that the cache has not stale yet,
    private – because no-cache doesn’t mean “private” by itself.
    3) the pages that marked as “exclude from caching” (php/html) it should be:
    Cache-control = “no-store”

    Probably, it would be reasonable to add “private, must-revalidate, max-age=0” to all Cache-control‘s to support http/1.0 browsers, because they don’t support nor no-cache neither no-store (but I’m not sure that they still exist).

    Plugin Support vupdraft

    (@vupdraft)

    Hi Alexander,

    Thank you for this, we are looking into your findings.

    Plugin Support vupdraft

    (@vupdraft)

    Thank you for providing us with a table. Before reviewing it, I have a few requests for modifications:

    1. Could you please include an “ID” column or something similar to uniquely identify each row? This would allow us to refer to specific rows in the future.

    2. Regarding the “mod_headers/mod_expires” column, could you clarify the meaning of “Yes,” “No,” and “Always”? Are you referring to whether the Apache module “mod_headers” is enabled or not? Or are you indicating the presence of an entry within the “.htaccess” file under the “<IfModule mod_headers.c>” block? Any explanation would be appreciated.

    3. It would be helpful if you could add another column labeled “WPO settings” that outlines the necessary setup in the WP-Optimize settings panel to achieve the same result. In other words, please provide detailed instructions on how to reproduce the issue, including any required changes to WP-Optimize settings, server environment, browser settings, or any other relevant factors.

    Thread Starter Alexander Guskov

    (@forcesail)

    Hello,

    1. Done
    2. The target of the table was to check the correction of work of the “mod_headers/mod_expires”.
      Actually, I was experimenting with “early” and “merge” as well but the result anyway is similar (not in the table)
      So, yes, it’s about “<IfModule?mod_headers.c>” block in the “.htaccess” file:
      “Yes” (created by WPO): Header set Cache-Control “private, must-revalidate”
      “Always (modified manually)”: Header always set Cache-Control “private, must-revalidate”
      “No (removed manually): (nothing)

      mod_expires.c:
      “Yes” (created by WPO): ExpiresByType text/html “access 1 day”
      “No” (removed manually) (nothing)
    3. I didn’t do anything with WPO settings or server settings or any other settings at all. Just changes .htaccess manually, turn on/off caching and requested the same page from incognito mode to be unlogged and normal mode to be logged while requesting.
      All the time WPO was active. All the time settings were:
      “Generate separate files for mobile devices”?= “on”
      “Serve cached pages to logged in users” = off

      Column “Server Cache” = “Yes”: “Enable page caching”=on & cache preloaded
      “Server Cache” = “No”: “Enable page caching”=off

      Browser: Chrome for desktop.
      I suppose all other to reproduce is clear from screenshots.

    WPO settings:
    ========================
    {“epoch_date”:1687279315983,”local_date”:”6/20/2023, 5:41:55 PM”,”network_site_url”:”https://forcesail.ru&#8221;,”data”:{“cache_settings”:{“enable_page_caching”:1,”enable_mobile_caching”:1,”enable_user_caching”:0,”page_cache_length_value”:”5″,”page_cache_length_unit”:”days”,”enable_schedule_preload”:1,”preload_schedule_type”:”wpo_use_cache_lifespan”,”cache_exception_urls”:[“/wp-admin/admin-ajax.php”,”/tests/“,”/yandexinfo.php”,”/regsem/“,”/application/“,”/paid/“,”/files/“,”/members/“],”cache_exception_cookies”:[“”],”cache_exception_conditional_tags”:[“”],”cache_exception_browser_agents”:[“”],”enable_browser_cache”:”true”,”browser_cache_expire_days”:”1″,”browser_cache_expire_hours”:”0″},”minify_settings”:{“enabled”:”true”,”enable_js”:”true”,”enable_css”:”true”,”html_minification”:”false”,”enable_js_minification”:”true”,”enable_merging_of_js”:”true”,”exclude_js”:”/ag-cf7-parameters/\r\n/sendform1/sendform.js\r\n/cf7-conditional-fields/\r\n/ml-slider/\r\n/popup-builder/\r\n/quiz-master-next/js/\r\n/all-in-one-seo-pack/dist/Lite/assets/\r\n”,”enable_defer_js”:”individual”,”async_js”:””,”defer_js_type”:”defer”,”defer_jquery”:”true”,”enable_js_trycatch”:”false”,”exclude_js_from_page_speed_tools”:”false”,”enable_css_minification”:”true”,”enable_merging_of_css”:”true”,”inline_css”:”true”,”exclude_css”:”/wp-content/plugins/popup-builder/public/css/theme.css1″,”async_css”:”/wp-content/awicons/css/animation.css\r\n/wp-content/awicons/css/animation.min.css\r\n/wp-content/awicons/css/wptouch-icons-codes.css\r\n/wp-content/awicons/css/wptouch-icons-embedded.css\r\n/wp-content/awicons/css/wptouch-icons.css “,”remove_print_mediatypes”:”false”,”exclude_css_from_page_speed_tools”:”false”,”gfonts_method”:”inherit”,”fawesome_method”:”inherit”,”remove_googlefonts”:”false”,”enable_display_swap”:”false”,”merge_inline_extra_css_js”:”true”,”clean_header_one”:”true”,”default_protocol”:”dynamic”,”disable_when_logged_in”:”false”,”emoji_removal”:”false”,”cache_lifespan”:”5″,”minify_advanced_tab”:”1″,”debug”:”false”,”edit_default_exclutions”:”false”},”smush_settings”:{“compression_server”:”resmushit”,”image_quality”:”75″,”lossy_compression”:true,”back_up_original”:true,”back_up_delete_after”:false,”back_up_delete_after_days”:”50″,”preserve_exif”:false,”autosmush”:false,”show_smush_metabox”:false,”webp_conversion”:false},”database_settings”:”enable-retention=true&retention-period=4&enable-revisions-retention=true&revisions-retention-count=2&schedule_type=wpo_weekly&wp-optimize-auto%5Brevisions%5D=true&wp-optimize-auto%5Bdrafts%5D=true&wp-optimize-auto%5Btrash%5D=true&wp-optimize-auto%5Bspams%5D=true&_wpnonce_db_settings=ac14e34bd0&_wp_http_referer=%2Fwp-admin%2Fadmin.php%3Fpage%3Dwpo_minify&enable-admin-bar=true&enable_cache_in_admin_bar=1&_wpnonce=ac14e34bd0&_wp_http_referer=%2Fwp-admin%2Fadmin.php%3Fpage%3Dwpo_minify&enable-auto-backup-scheduled=0&enable-schedule=0&wp-optimize-auto[optimize]=0&wp-optimize-auto[unapproved]=0&wp-optimize-auto[transient]=0&wp-optimize-auto[usermeta]=0″}}

    Plugin Support vupdraft

    (@vupdraft)

    Let’s start with #5. Based on your instructions, here are the steps to reproduce the issue:

    1. Reset WP-Optimize settings to default by clicking on the following link, screenshot: https://prnt.sc/Hma2r_BeKzki
    2. Enable “Browser static file caching” and set the expiration time to 1 day, screenshot: https://prnt.sc/smdoVj7l2zlG
    3. Visit a page while logged in.
    4. In the Network tab, check the response headers. You should see the following:
        a) cache-control: no-cache, must-revalidate, max-age=0
        b) cache-control: private, must-revalidate

    == Expected result ==

    In step-4, the response header should be:
        cache-control: no-cache, must-revalidate, max-age=0

    Plugin Support vupdraft

    (@vupdraft)

    Please let us know if there are any corrections needed, and provide the correct reproduction steps in the format provided above. It’s important to ensure that we are both on the same page.

    Thread Starter Alexander Guskov

    (@forcesail)

    Ok. I have done it.
    1) Reset WP-Optimize settings
    – it switch off cache and minimizing
    – it sets Browser static file caching settings (via headers) to 28 days but remove all regarding mod_headers/mod_expires from .htaccess.
    As the result header of a logged-in page is:
    cache-control: no-cache, must-revalidate, max-age=0

    2) Enable “Browser static file caching” and set the expiration time to 1 day,
    – adds mod_headers/mod_expires to.htaccess.
    As the result header of a logged-in page is:
    cache-control: no-cache, must-revalidate, max-age=0
    cache-control: private, must-revalidate


    Enjoy: https://forcesail.ru/Cache-Control/202306231.mp4

    Plugin Support vupdraft

    (@vupdraft)

    Hi Alexander,

    As you are modifying the .htaccess file manually, you may get unexpected response headers. We would not recommend you do this.

    Thread Starter Alexander Guskov

    (@forcesail)

    Of course, that before to modify it I saved it, I did it only for test and then returned the original. So, it’s not a point.

    Plugin Support vupdraft

    (@vupdraft)

    Hi Alexander

    Can you provide the exact steps, in exact order, about how to reproduce the issue, and what results you expecting with each step. If you are making any modifications to the .htaccess file could you explicitly mention it in the steps. If you could, could you provide screenshots for each of the steps?

Viewing 15 replies - 1 through 15 (of 25 total)
  • The topic ‘cache-control mess in the headers and posible leak of secure’ is closed to new replies.