Make WordPress Core

Changeset 56664


Ignore:
Timestamp:
09/22/2023 07:06:45 PM (3 years ago)
Author:
adamsilverstein
Message:

Security: remove the cron event that checked for https support.

Fix an issue where a cron job ran every 12 hours to check for https support - even when https support was already enabled. The check is now run only when the user visits the Site Health page. Reducing the unneeded requests lowers the impact and load of hosting WordPress sites.

The wp_update_https_detection_errors function is deprecated and the https_detection_errors option that was previously set by the cron job is no longer maintained. The pre_wp_update_https_detection_errors filter is deprecated and replaced by the pre_wp_get_https_detection_errors filter which serves the same function.

Props audrasjb, johnbillion, Michi91.
Fixes #58494.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/class-wp-site-health.php

    r56549 r56664  
    15561556        public function get_test_https_status() {
    15571557                /*
    1558                  * Enforce fresh HTTPS detection results. This is normally invoked by using cron,
    1559                  * but for Site Health it should always rely on the latest results.
     1558                 * Check HTTPS detection results.
    15601559                 */
    1561                 wp_update_https_detection_errors();
     1560                $errors = wp_get_https_detection_errors();
    15621561
    15631562                $default_update_url = wp_get_default_update_https_url();
  • trunk/src/wp-admin/includes/upgrade.php

    r56658 r56664  
    23412341                // Enable attachment pages.
    23422342                update_option( 'wp_attachment_pages_enabled', 1 );
     2343
     2344                // Remove the wp_https_detection cron. Https status is checked directly in an async Site Health check.
     2345                $scheduled = wp_get_scheduled_event( 'wp_https_detection' );
     2346                if ( $scheduled ) {
     2347                        wp_clear_scheduled_hook( 'wp_https_detection' );
     2348                }
    23432349        }
    23442350}
  • trunk/src/wp-includes/default-filters.php

    r56529 r56664  
    388388}
    389389
    390 // HTTPS detection.
    391 add_action( 'init', 'wp_schedule_https_detection' );
    392 add_action( 'wp_https_detection', 'wp_update_https_detection_errors' );
    393 add_filter( 'cron_request', 'wp_cron_conditionally_prevent_sslverify', 9999 );
    394 
    395390// HTTPS migration.
    396391add_action( 'update_option_home', 'wp_update_https_migration_required', 10, 2 );
  • trunk/src/wp-includes/deprecated.php

    r56500 r56664  
    58715871        add_action( 'admin_init', $fn_generate_and_enqueue_editor_styles );
    58725872}
     5873
     5874/**
     5875 * Runs a remote HTTPS request to detect whether HTTPS supported, and stores potential errors.
     5876 *
     5877 * This internal function is called by a regular Cron hook to ensure HTTPS support is detected and maintained.
     5878 *
     5879 * @since 5.7.0
     5880 * @deprecated 6.4.0 The `wp_update_https_detection_errors()` function is no longer used and has been replaced by
     5881 *                   `wp_get_https_detection_errors()`. Previously the function was called by a regular Cron hook to
     5882 *                    update the `https_detection_errors` option, but this is no longer necessary as the errors are
     5883 *                    retrieved directly in Site Health and no longer used outside of Site Health.
     5884 * @access private
     5885 */
     5886function wp_update_https_detection_errors() {
     5887        _deprecated_function( __FUNCTION__, '6.4.0' );
     5888
     5889        /**
     5890         * Short-circuits the process of detecting errors related to HTTPS support.
     5891         *
     5892         * Returning a `WP_Error` from the filter will effectively short-circuit the default logic of trying a remote
     5893         * request to the site over HTTPS, storing the errors array from the returned `WP_Error` instead.
     5894         *
     5895         * @since 5.7.0
     5896         * @deprecated 6.4.0 The `wp_update_https_detection_errors` filter is no longer used and has been replaced by `pre_wp_get_https_detection_errors`.
     5897         *
     5898         * @param null|WP_Error $pre Error object to short-circuit detection,
     5899         *                           or null to continue with the default behavior.
     5900         */
     5901        $support_errors = apply_filters( 'pre_wp_update_https_detection_errors', null );
     5902        if ( is_wp_error( $support_errors ) ) {
     5903                update_option( 'https_detection_errors', $support_errors->errors );
     5904                return;
     5905        }
     5906
     5907        $support_errors = wp_get_https_detection_errors();
     5908
     5909        update_option( 'https_detection_errors', $support_errors );
     5910}
  • trunk/src/wp-includes/https-detection.php

    r56191 r56664  
    8787 * This internal function is called by a regular Cron hook to ensure HTTPS support is detected and maintained.
    8888 *
    89  * @since 5.7.0
     89 * @since 6.4.0
    9090 * @access private
    9191 */
    92 function wp_update_https_detection_errors() {
     92function wp_get_https_detection_errors() {
    9393        /**
    9494         * Short-circuits the process of detecting errors related to HTTPS support.
     
    9797         * request to the site over HTTPS, storing the errors array from the returned `WP_Error` instead.
    9898         *
    99          * @since 5.7.0
     99         * @since 6.4.0
    100100         *
    101101         * @param null|WP_Error $pre Error object to short-circuit detection,
    102102         *                           or null to continue with the default behavior.
     103         * @return null|WP_Error Error object if HTTPS detection errors are found, null otherwise.
    103104         */
    104         $support_errors = apply_filters( 'pre_wp_update_https_detection_errors', null );
     105        $support_errors = apply_filters( 'pre_wp_get_https_detection_errors', null );
    105106        if ( is_wp_error( $support_errors ) ) {
    106                 update_option( 'https_detection_errors', $support_errors->errors );
    107                 return;
     107                return $support_errors->errors;
    108108        }
    109109
     
    154154        }
    155155
    156         update_option( 'https_detection_errors', $support_errors->errors );
    157 }
    158 
    159 /**
    160  * Schedules the Cron hook for detecting HTTPS support.
    161  *
    162  * @since 5.7.0
    163  * @access private
    164  */
    165 function wp_schedule_https_detection() {
    166         if ( wp_installing() ) {
    167                 return;
    168         }
    169 
    170         if ( ! wp_next_scheduled( 'wp_https_detection' ) ) {
    171                 wp_schedule_event( time(), 'twicedaily', 'wp_https_detection' );
    172         }
    173 }
    174 
    175 /**
    176  * Disables SSL verification if the 'cron_request' arguments include an HTTPS URL.
    177  *
    178  * This prevents an issue if HTTPS breaks, where there would be a failed attempt to verify HTTPS.
    179  *
    180  * @since 5.7.0
    181  * @access private
    182  *
    183  * @param array $request The cron request arguments.
    184  * @return array The filtered cron request arguments.
    185  */
    186 function wp_cron_conditionally_prevent_sslverify( $request ) {
    187         if ( 'https' === wp_parse_url( $request['url'], PHP_URL_SCHEME ) ) {
    188                 $request['args']['sslverify'] = false;
    189         }
    190         return $request;
     156        return $support_errors->errors;
    191157}
    192158
  • trunk/tests/phpunit/tests/https-detection.php

    r56559 r56664  
    5353                update_option( 'https_detection_errors', $wp_error->errors );
    5454                $this->assertFalse( wp_is_https_supported() );
    55         }
    56 
    57         /**
    58          * @ticket 47577
    59          * @ticket 52484
    60          */
    61         public function test_wp_update_https_detection_errors() {
    62                 // Set HTTP URL, the request below should use its HTTPS version.
    63                 update_option( 'home', 'http://example.com/' );
    64                 add_filter( 'pre_http_request', array( $this, 'record_request_url' ), 10, 3 );
    65 
    66                 // If initial request succeeds, all good.
    67                 add_filter( 'pre_http_request', array( $this, 'mock_success_with_sslverify' ), 10, 2 );
    68                 wp_update_https_detection_errors();
    69                 $this->assertSame( array(), get_option( 'https_detection_errors' ) );
    70 
    71                 // If initial request fails and request without SSL verification succeeds,
    72                 // return 'ssl_verification_failed' error.
    73                 add_filter( 'pre_http_request', array( $this, 'mock_error_with_sslverify' ), 10, 2 );
    74                 add_filter( 'pre_http_request', array( $this, 'mock_success_without_sslverify' ), 10, 2 );
    75                 wp_update_https_detection_errors();
    76                 $this->assertSame(
    77                         array( 'ssl_verification_failed' => array( __( 'SSL verification failed.' ) ) ),
    78                         get_option( 'https_detection_errors' )
    79                 );
    80 
    81                 // If both initial request and request without SSL verification fail,
    82                 // return 'https_request_failed' error.
    83                 add_filter( 'pre_http_request', array( $this, 'mock_error_with_sslverify' ), 10, 2 );
    84                 add_filter( 'pre_http_request', array( $this, 'mock_error_without_sslverify' ), 10, 2 );
    85                 wp_update_https_detection_errors();
    86                 $this->assertSame(
    87                         array( 'https_request_failed' => array( __( 'HTTPS request failed.' ) ) ),
    88                         get_option( 'https_detection_errors' )
    89                 );
    90 
    91                 // If request succeeds, but response is not 200, return error with
    92                 // 'bad_response_code' error code.
    93                 add_filter( 'pre_http_request', array( $this, 'mock_not_found' ), 10, 2 );
    94                 wp_update_https_detection_errors();
    95                 $this->assertSame(
    96                         array( 'bad_response_code' => array( 'Not Found' ) ),
    97                         get_option( 'https_detection_errors' )
    98                 );
    99 
    100                 // If request succeeds, but response was not generated by this
    101                 // WordPress site, return error with 'bad_response_source' error code.
    102                 add_filter( 'pre_http_request', array( $this, 'mock_bad_source' ), 10, 2 );
    103                 wp_update_https_detection_errors();
    104                 $this->assertSame(
    105                         array( 'bad_response_source' => array( 'It looks like the response did not come from this site.' ) ),
    106                         get_option( 'https_detection_errors' )
    107                 );
    108 
    109                 // Check that the requests are made to the correct URL.
    110                 $this->assertSame( 'https://example.com/', $this->last_request_url );
    111         }
    112 
    113         /**
    114          * @ticket 47577
    115          */
    116         public function test_pre_wp_update_https_detection_errors() {
    117                 // Override to enforce no errors being detected.
    118                 add_filter(
    119                         'pre_wp_update_https_detection_errors',
    120                         static function () {
    121                                 return new WP_Error();
    122                         }
    123                 );
    124                 wp_update_https_detection_errors();
    125                 $this->assertSame( array(), get_option( 'https_detection_errors' ) );
    126 
    127                 // Override to enforce an error being detected.
    128                 add_filter(
    129                         'pre_wp_update_https_detection_errors',
    130                         static function () {
    131                                 return new WP_Error(
    132                                         'ssl_verification_failed',
    133                                         'Bad SSL certificate.'
    134                                 );
    135                         }
    136                 );
    137                 wp_update_https_detection_errors();
    138                 $this->assertSame(
    139                         array( 'ssl_verification_failed' => array( 'Bad SSL certificate.' ) ),
    140                         get_option( 'https_detection_errors' )
    141                 );
    142         }
    143 
    144         /**
    145          * @ticket 47577
    146          */
    147         public function test_wp_schedule_https_detection() {
    148                 wp_schedule_https_detection();
    149                 $this->assertSame( 'twicedaily', wp_get_schedule( 'wp_https_detection' ) );
    150         }
    151 
    152         /**
    153          * @ticket 47577
    154          */
    155         public function test_wp_cron_conditionally_prevent_sslverify() {
    156                 // If URL is not using HTTPS, don't set 'sslverify' to false.
    157                 $request = array(
    158                         'url'  => 'http://example.com/',
    159                         'args' => array( 'sslverify' => true ),
    160                 );
    161                 $this->assertSame( $request, wp_cron_conditionally_prevent_sslverify( $request ) );
    162 
    163                 // If URL is using HTTPS, set 'sslverify' to false.
    164                 $request                       = array(
    165                         'url'  => 'https://example.com/',
    166                         'args' => array( 'sslverify' => true ),
    167                 );
    168                 $expected                      = $request;
    169                 $expected['args']['sslverify'] = false;
    170                 $this->assertSame( $expected, wp_cron_conditionally_prevent_sslverify( $request ) );
    17155        }
    17256
Note: See TracChangeset for help on using the changeset viewer.