Forum Replies Created

Viewing 15 replies - 1 through 15 (of 76 total)
  • Thread Starter p15h

    (@prestonwordsworth)

    Thanks for being so helpful, Florian! Yeah, I realised the space was the culprit once you called it out. And I’ve been able to quickly identify the source (WebP Express).

    I’ll report back and close this thread once it’s resolved upstream.

    Thread Starter p15h

    (@prestonwordsworth)

    Right, the two spaces were actually in the HTML. Thanks for catching that!

    I can’t explain why they are there off the top of my head. Please do let me know if you have any idea how this might’ve happened.

    Thread Starter p15h

    (@prestonwordsworth)

    One thing that could usefully be done is to expose the WPACU_ALLOW_ONLY_UNLOAD_RULE variable in the dashboard UI.

    Thread Starter p15h

    (@prestonwordsworth)

    Thanks for pointing that out, Florian! Here’s the HTML in question

    <img decoding="async" width="580" height="580" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20580%20580%22%3E%3C%2Fsvg%3E" class="attachment-large size-large wp-image-10932 lazyload" alt="" srcset="data:image/svg+xml,  %3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20580%20580%22%3E%3C%2Fsvg%3E 580w" sizes="(max-width: 580px) 100vw, 580px" data-srcset="responsive image urls" data-src="original url">

    Is this what you expect? Or could there be a conflict say with Elementor?

    Console error in Chrome:

    GET data:image/svg+xml net::ERR_INVALID_URL

    In Safari:

    [Error] Failed to load resource: Data URL decoding failed (dat…xml, line 0)    data:image/svg+xml
    Thread Starter p15h

    (@prestonwordsworth)

    A quick follow-up:

    1. My statement about 500k+ response was found to be incorrect on double-checking the logs. It was in the neighbourhood of 150k.
    2. This still exceeds nginx’s default proxy_buffers 8 4k; by a lot. Of course, as a last resort, one can always increase proxy_buffers, but I’m wondering if it is absolutely necessary for this plugin to emit 150k responses.
    Thread Starter p15h

    (@prestonwordsworth)

    That makes sense. Great to know!

    Thread Starter p15h

    (@prestonwordsworth)

    Apologies for the delay. I’ve just had time to look at the code, so here’s why your script is being blocked by browsers:

    if ($attempts > 10) {
    add_action("wp_head", "wordfence::addSyncAttackDataAjax");
    add_action("login_head", "wordfence::addSyncAttackDataAjax");
    add_action("admin_head", "wordfence::addSyncAttackDataAjax");
    } else {
    update_site_option("wordfence_syncAttackDataAttempts", ++$attempts);
    wp_remote_post(
    add_query_arg(
    "wordfence_syncAttackData",
    microtime(true),
    home_url("/")
    ),
    [
    "timeout" => 0.01,
    "blocking" => false,
    "sslverify" => apply_filters("https_local_ssl_verify", false),
    ]
    );
    }

    The second method is OK because wp_remote_post is a loopback request that bypasses the browser. The trouble is with the first method, which gets triggered like you say when there’s a bout of attacks. Let’s see what it’s doing:

    public static function addSyncAttackDataAjax() {        
    $URL = home_url('/?wordfence_syncAttackData=' . microtime(true));
    $URL = esc_url(preg_replace('/^https?:/i', '', $URL));
    // Load as external script async so we don't slow page down.
    echo "<script type=\"text/javascript\" src=\"$URL\" async></script>";
    }

    So that’s why it’s getting blocked! The type attribute won’t work as intended when a site is using a caching solution that’s set to ignore query strings, a common technique to obviate query string-based DDoS attacks. That’s because a request like this would simply return the cache of home URL with a MIME type of text/html, triggering a nosniff block by browsers:

    Refused to execute https://www.example.com/?wordfence_syncAttackData=1728611106.9776 as script because "X-Content-Type-Options: nosniff" was given and its Content-Type is not a script MIME type.

    What we would like to see is a toggle that lets webmasters to opt out of this ‘script’ method on sites that have this rather common setup.

    Thread Starter p15h

    (@prestonwordsworth)

    I’ve now identified the reason why populate_enqueue doesn’t get triggered on post update: it’s because it’s using the transition_post_status hook, which only fires when you refresh the page, whereas post update is usually done via Ajax.

    So, there’s two ways to go about this. One could use the edit_post hook like in the purge action above. Or one could register a custom hook:

    add_action('wp_ajax_' . WPACU_PLUGIN_ID . '_preload',     array($this, 'ajaxPreloadGuest'), PHP_INT_MAX);
    /**
    * This is triggered when /admin/admin-ajax.php is called (default WordPress AJAX handler)
    */
    public function ajaxPreloadGuest()
    {
    // Check nonce
    if ( ! isset( $_POST['wpacu_nonce'] ) || ! wp_verify_nonce( $_POST['wpacu_nonce'], 'wpacu_ajax_preload_url_nonce' ) ) {
    echo 'Error: The security nonce is not valid.';
    exit();
    }

    $pageUrl = isset($_POST['page_url']) ? $_POST['page_url'] : false;
    $pageUrlDomain = parse_url($pageUrl, PHP_URL_HOST);
    $pageUrlPreload = add_query_arg( array( 'wpacu_preload' => 1 ), $pageUrl );

    // Check if the URL is valid
    if (! filter_var($pageUrlPreload, FILTER_VALIDATE_URL)) {
    echo 'The URL
    '.$pageUrlPreload.' is not valid.';
    exit();
    }

    // Check the domain from "page_url" parameter
    if (strpos(site_url(), $pageUrlDomain) === false) {
    echo 'Error: Possible hacking attempt! The host name of the requested URL is not the same as the one of "Site Address (URL)" from "Settings" - "General".';
    exit();
    }

    // Check privileges
    if (! Menu::userCanAccessAssetCleanUp()) {
    echo 'Error: Not enough privileges to perform this action.';
    exit();
    }

    $response = wp_remote_get($pageUrlPreload);

    if (is_wp_error($response)) {
    // Any error generated during the fetch? Print it
    echo 'Error: '.$response->get_error_code();
    } else {
    // No errors
    echo 'Status Code: '.wp_remote_retrieve_response_code($response).' / Page URL (preload): ' . $pageUrlPreload . "\n\n";
    echo isset($response['body']) ? $response['body'] : 'No "body" key found from wp_remote_get(), the preload might not have triggered';
    }

    exit();
    }
    /**
    * This is triggered when /admin/admin-ajax.php is called (default WordPress AJAX handler)
    */
    public function ajaxPreloadGuest()
    {
    // Check nonce
    if ( ! isset( $_POST['wpacu_nonce'] ) || ! wp_verify_nonce( $_POST['wpacu_nonce'], 'wpacu_ajax_preload_url_nonce' ) ) {
    echo 'Error: The security nonce is not valid.';
    exit();
    }

    $pageUrl = isset($_POST['page_url']) ? $_POST['page_url'] : false;
    $pageUrlDomain = parse_url($pageUrl, PHP_URL_HOST);
    $pageUrlPreload = add_query_arg( array( 'wpacu_preload' => 1 ), $pageUrl );

    // Check if the URL is valid
    if (! filter_var($pageUrlPreload, FILTER_VALIDATE_URL)) {
    echo 'The URL '.$pageUrlPreload.' is not valid.';
    exit();
    }

    // Check the domain from "page_url" parameter
    if (strpos(site_url(), $pageUrlDomain) === false) {
    echo 'Error: Possible hacking attempt! The host name of the requested URL is not the same as the one of "Site Address (URL)" from "Settings" - "General".';
    exit();
    }

    // Check privileges
    if (! Menu::userCanAccessAssetCleanUp()) {
    echo 'Error: Not enough privileges to perform this action.';
    exit();
    }

    $response = wp_remote_get($pageUrlPreload);

    if (is_wp_error($response)) {
    // Any error generated during the fetch? Print it
    echo 'Error: '.$response->get_error_code();
    } else {
    // No errors
    echo 'Status Code: '.wp_remote_retrieve_response_code($response).' / Page URL (preload): ' . $pageUrlPreload . "\n\n";
    echo isset($response['body']) ? $response['body'] : 'No "body" key found from wp_remote_get(), the preload might not have triggered';
    }

    exit();
    }
    p15h

    (@prestonwordsworth)

    A good starting point might be to tick Add all public posts (of any type) and taxonomies of this site as entry points, use 1 for depth, tick scripts, styles and images for assets preloading, and tick On their publication and edit. Run it manually once, and let it be triggered by each edit thereafter.

    For more advanced usage, look up any terms unfamiliar to you on the internet to decide whether each particular setting is relevant to your case. RFC 9111 is always worth reading.

    Thread Starter p15h

    (@prestonwordsworth)

    Reference on the first point can be found here: https://developers.cloudflare.com/cache/concepts/default-cache-behavior/.

    For similar reasons, the second snippet can be further reduced to

    Header set Cache-Control "no-cache" "expr=%{CONTENT_TYPE} =~ m#(?:application/xml|text/xsl)#"

    and still have the same effect.

    p15h

    (@prestonwordsworth)

    Nice to have your perspective, Saumya.

    Let me come back to kpbryce132‘s original remark and just add one more point. The root cause of all this fuss around v5.x is really that the new plugin is not production-ready. We’d expect that a commercial outfit such as Optimole had a mature process for testing and releasing software. That’s not the case here.

    So, yeah, if Optimole simply add paid features and don’t break anything, fine. What’s deplorable here is they took over the plugin and start breaking people’s production sites, as many a post here attests to.

    p15h

    (@prestonwordsworth)

    @kpbryce132, I’m glad you brought up the general issue. A lot of us don’t like the direction this plugin is taking. Presumably, the original author sold it to Optimole, who are understandably looking to monetise the plugin.

    But we old users prefer a plugin that does one thing well, at no cost to us: configuring CF page cache. Which v4.x did well.

    So it’s probably time for someone to fork v4.7.13 and maintain it as a separate plugin for the community, fixing the occasional bugs as they arise. @isaumya, you are obviously the person best suited for the task. But I guess others could step in if you’re personally happy with v5.x.

    Thread Starter p15h

    (@prestonwordsworth)

    This is a feature that’s actually already available when Gutenberg is on. The required configuration on Pods’ side is documented here: https://pods.io/2018/12/05/pods-2-7-10-release-gutenberg-and-wp-5-0-compatibility/.

    Thread Starter p15h

    (@prestonwordsworth)

    And would it be possible for you to automate this in the plugin using WP’s get_site_url?

    Thread Starter p15h

    (@prestonwordsworth)

    That makes sense. In that case, a 303 redirect is probably the way to go.

Viewing 15 replies - 1 through 15 (of 76 total)