Make WordPress Core

Changeset 50072


Ignore:
Timestamp:
01/29/2021 07:09:49 PM (6 years ago)
Author:
flixos90
Message:

Security, Site Health: Improve accuracy in messaging about HTTPS support.

Following up on [49904], this changeset focuses mainly on improving the guidance about the current state of HTTPS in Site Health.

  • Correct the existing copy to indicate that both the Site Address and the WordPress Address need to be changed to fully switch to HTTPS.
  • Link to the respective input fields via anchor links rather than to the overall General Settings screen.
  • Show different copy if the site is using HTTPS for the WordPress Address (for example to have only the administration panel in HTTPS), but not for the Site Address.
  • Inform the user about potential problems even when the site is already using HTTPS, for example if the SSL certificate was no longer valid.
  • Always rely on fresh information for determining HTTPS support issues in Site Health, and therefore change the https_status test to become asynchronous.
  • Rename the new private wp_is_owned_html_output() function to a more appropriate wp_is_local_html_output().

Props adamsilverstein, flixos90, johnjamesjacoby, timothyblynjacobs.
See #47577.

Location:
trunk
Files:
6 edited

Legend:

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

    r50041 r50072  
    109109                        // Don't run https test on development environments.
    110110                        if ( $this->is_development_environment() ) {
    111                                 unset( $tests['direct']['https_status'] );
     111                                unset( $tests['async']['https_status'] );
    112112                        }
    113113
     
    14991499         */
    15001500        public function get_test_https_status() {
     1501                // Enforce fresh HTTPS detection results. This is normally invoked by using cron, but for Site Health it should
     1502                // always rely on the latest results.
     1503                wp_update_https_detection_errors();
     1504
    15011505                $result = array(
    15021506                        'label'       => __( 'Your website is using an active HTTPS connection' ),
     
    15221526
    15231527                if ( ! wp_is_using_https() ) {
     1528                        // If the website is not using HTTPS, provide more information about whether it is supported and how it can
     1529                        // be enabled.
    15241530                        $result['status'] = 'critical';
    15251531                        $result['label']  = __( 'Your website does not use HTTPS' );
    15261532
    1527                         if ( is_ssl() ) {
    1528                                 $result['description'] = sprintf(
    1529                                         '<p>%s</p>',
    1530                                         sprintf(
    1531                                                 /* translators: %s: URL to General Settings screen. */
    1532                                                 __( 'You are accessing this website using HTTPS, but your <a href="%s">WordPress Address</a> is not set up to use HTTPS by default.' ),
    1533                                                 esc_url( admin_url( 'options-general.php' ) )
    1534                                         )
    1535                                 );
     1533                        if ( wp_is_site_url_using_https() ) {
     1534                                if ( is_ssl() ) {
     1535                                        $result['description'] = sprintf(
     1536                                                '<p>%s</p>',
     1537                                                sprintf(
     1538                                                        /* translators: %s: URL to Settings > General > Site Address. */
     1539                                                        __( 'You are accessing this website using HTTPS, but your <a href="%s">Site Address</a> is not set up to use HTTPS by default.' ),
     1540                                                        esc_url( admin_url( 'options-general.php' ) . '#home' )
     1541                                                )
     1542                                        );
     1543                                } else {
     1544                                        $result['description'] = sprintf(
     1545                                                '<p>%s</p>',
     1546                                                sprintf(
     1547                                                        /* translators: %s: URL to Settings > General > Site Address. */
     1548                                                        __( 'Your <a href="%s">Site Address</a> is not set up to use HTTPS.' ),
     1549                                                        esc_url( admin_url( 'options-general.php' ) . '#home' )
     1550                                                )
     1551                                        );
     1552                                }
    15361553                        } else {
    1537                                 $result['description'] = sprintf(
    1538                                         '<p>%s</p>',
    1539                                         sprintf(
    1540                                                 /* translators: %s: URL to General Settings screen. */
    1541                                                 __( 'Your <a href="%s">WordPress Address</a> is not set up to use HTTPS.' ),
    1542                                                 esc_url( admin_url( 'options-general.php' ) )
    1543                                         )
    1544                                 );
     1554                                if ( is_ssl() ) {
     1555                                        $result['description'] = sprintf(
     1556                                                '<p>%s</p>',
     1557                                                sprintf(
     1558                                                        /* translators: 1: URL to Settings > General > WordPress Address, 2: URL to Settings > General > Site Address. */
     1559                                                        __( 'You are accessing this website using HTTPS, but your <a href="%1$s">WordPress Address</a> and <a href="%2$s">Site Address</a> are not set up to use HTTPS by default.' ),
     1560                                                        esc_url( admin_url( 'options-general.php' ) . '#siteurl' ),
     1561                                                        esc_url( admin_url( 'options-general.php' ) . '#home' )
     1562                                                )
     1563                                        );
     1564                                } else {
     1565                                        $result['description'] = sprintf(
     1566                                                '<p>%s</p>',
     1567                                                sprintf(
     1568                                                        /* translators: 1: URL to Settings > General > WordPress Address, 2: URL to Settings > General > Site Address. */
     1569                                                        __( 'Your <a href="%1$s">WordPress Address</a> and <a href="%2$s">Site Address</a> are not set up to use HTTPS.' ),
     1570                                                        esc_url( admin_url( 'options-general.php' ) . '#siteurl' ),
     1571                                                        esc_url( admin_url( 'options-general.php' ) . '#home' )
     1572                                                )
     1573                                        );
     1574                                }
    15451575                        }
    15461576
     
    15621592                                );
    15631593                        }
     1594                } elseif ( ! wp_is_https_supported() ) {
     1595                        // If the website is using HTTPS, but HTTPS is actually not supported, inform the user about the potential
     1596                        // problems.
     1597                        $result['status'] = 'critical';
     1598                        $result['label']  = __( 'There are problems with the HTTPS connection of your website' );
     1599
     1600                        $https_detection_errors = get_option( 'https_detection_errors' );
     1601                        if ( ! empty( $https_detection_errors['ssl_verification_failed'] ) ) {
     1602                                $result['description'] = sprintf(
     1603                                        '<p>%s</p>',
     1604                                        sprintf(
     1605                                                /* translators: %s: URL to Settings > General > WordPress Address. */
     1606                                                __( 'Your <a href="%s">WordPress Address</a> is set up to use HTTPS, but the SSL certificate appears to be invalid.' ),
     1607                                                esc_url( admin_url( 'options-general.php' ) . '#siteurl' )
     1608                                        )
     1609                                );
     1610                        } else {
     1611                                $result['description'] = sprintf(
     1612                                        '<p>%s</p>',
     1613                                        sprintf(
     1614                                                /* translators: %s: URL to Settings > General > WordPress Address. */
     1615                                                __( 'Your <a href="%s">WordPress Address</a> is set up to use HTTPS, but your website appears to be unavailable when using an HTTPS connection.' ),
     1616                                                esc_url( admin_url( 'options-general.php' ) . '#siteurl' )
     1617                                        )
     1618                                );
     1619                        }
     1620                        $result['description'] .= sprintf(
     1621                                '<p>%s</p>',
     1622                                __( 'Talk to your web host about resolving this HTTPS issue for your website.' )
     1623                        );
    15641624                }
    15651625
     
    22012261                                        'test'  => 'utf8mb4_support',
    22022262                                ),
    2203                                 'https_status'              => array(
    2204                                         'label' => __( 'HTTPS status' ),
    2205                                         'test'  => 'https_status',
    2206                                 ),
    22072263                                'ssl_support'               => array(
    22082264                                        'label' => __( 'Secure communication' ),
     
    22482304                                        'has_rest'          => true,
    22492305                                        'async_direct_test' => array( WP_Site_Health::get_instance(), 'get_test_loopback_requests' ),
     2306                                ),
     2307                                'https_status'         => array(
     2308                                        'label'             => __( 'HTTPS status' ),
     2309                                        'test'              => rest_url( 'wp-site-health/v1/tests/https-status' ),
     2310                                        'has_rest'          => true,
     2311                                        'async_direct_test' => array( WP_Site_Health::get_instance(), 'get_test_https_status' ),
    22502312                                ),
    22512313                                'authorization_header' => array(
     
    26152677                // Don't run https test on development environments.
    26162678                if ( $this->is_development_environment() ) {
    2617                         unset( $tests['direct']['https_status'] );
     2679                        unset( $tests['async']['https_status'] );
    26182680                }
    26192681
  • trunk/src/wp-includes/https-detection.php

    r49909 r50072  
    1010 * Checks whether the website is using HTTPS.
    1111 *
    12  * This is based on whether the home and site URL are using HTTPS.
    13  *
    14  * @since 5.7.0
     12 * This is based on whether both the home and site URL are using HTTPS.
     13 *
     14 * @since 5.7.0
     15 * @see wp_is_home_url_using_https()
     16 * @see wp_is_site_url_using_https()
    1517 *
    1618 * @return bool True if using HTTPS, false otherwise.
    1719 */
    1820function wp_is_using_https() {
    19         if ( 'https' !== wp_parse_url( home_url(), PHP_URL_SCHEME ) ) {
     21        if ( ! wp_is_home_url_using_https() ) {
    2022                return false;
    2123        }
    2224
     25        return wp_is_site_url_using_https();
     26}
     27
     28/**
     29 * Checks whether the current site URL is using HTTPS.
     30 *
     31 * @since 5.7.0
     32 * @see home_url()
     33 *
     34 * @return bool True if using HTTPS, false otherwise.
     35 */
     36function wp_is_home_url_using_https() {
     37        return 'https' === wp_parse_url( home_url(), PHP_URL_SCHEME );
     38}
     39
     40/**
     41 * Checks whether the current site's URL where WordPress is stored is using HTTPS.
     42 *
     43 * This checks the URL where WordPress application files (e.g. wp-blog-header.php or the wp-admin/ folder) are
     44 * accessible.
     45 *
     46 * @since 5.7.0
     47 * @see site_url()
     48 *
     49 * @return bool True if using HTTPS, false otherwise.
     50 */
     51function wp_is_site_url_using_https() {
    2352        // Use direct option access for 'siteurl' and manually run the 'site_url'
    24         // filter because site_url() will adjust the scheme based on what the
     53        // filter because `site_url()` will adjust the scheme based on what the
    2554        // current request is using.
    2655        /** This filter is documented in wp-includes/link-template.php */
    2756        $site_url = apply_filters( 'site_url', get_option( 'siteurl' ), '', null, null );
    2857
    29         if ( 'https' !== wp_parse_url( $site_url, PHP_URL_SCHEME ) ) {
    30                 return false;
    31         }
    32 
    33         return true;
     58        return 'https' === wp_parse_url( $site_url, PHP_URL_SCHEME );
    3459}
    3560
     
    105130                if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
    106131                        $support_errors->add( 'bad_response_code', wp_remote_retrieve_response_message( $response ) );
    107                 } elseif ( false === wp_is_owned_html_output( wp_remote_retrieve_body( $response ) ) ) {
     132                } elseif ( false === wp_is_local_html_output( wp_remote_retrieve_body( $response ) ) ) {
    108133                        $support_errors->add( 'bad_response_source', __( 'It looks like the response did not come from this site.' ) );
    109134                }
     
    160185 * @return bool|null True/false for whether HTML was generated by this site, null if unable to determine.
    161186 */
    162 function wp_is_owned_html_output( $html ) {
     187function wp_is_local_html_output( $html ) {
    163188        // 1. Check if HTML includes the site's Really Simple Discovery link.
    164189        if ( has_action( 'wp_head', 'rsd_link' ) ) {
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-site-health-controller.php

    r49716 r50072  
    8080                                        'permission_callback' => function () {
    8181                                                return $this->validate_request_permission( 'loopback_requests' );
     82                                        },
     83                                ),
     84                                'schema' => array( $this, 'get_public_item_schema' ),
     85                        )
     86                );
     87
     88                register_rest_route(
     89                        $this->namespace,
     90                        sprintf(
     91                                '/%s/%s',
     92                                $this->rest_base,
     93                                'https-status'
     94                        ),
     95                        array(
     96                                array(
     97                                        'methods'             => 'GET',
     98                                        'callback'            => array( $this, 'test_https_status' ),
     99                                        'permission_callback' => function () {
     100                                                return $this->validate_request_permission( 'https_status' );
    82101                                        },
    83102                                ),
     
    198217                $this->load_admin_textdomain();
    199218                return $this->site_health->get_test_loopback_requests();
     219        }
     220
     221        /**
     222         * Checks that the site's frontend can be accessed over HTTPS.
     223         *
     224         * @since 5.7.0
     225         *
     226         * @return array
     227         */
     228        public function test_https_status() {
     229                $this->load_admin_textdomain();
     230                return $this->site_health->get_test_https_status();
    200231        }
    201232
  • trunk/tests/phpunit/tests/https-detection.php

    r49904 r50072  
    142142         * @ticket 47577
    143143         */
    144         public function test_wp_is_owned_html_output_via_rsd_link() {
     144        public function test_wp_is_local_html_output_via_rsd_link() {
    145145                // HTML includes RSD link.
    146146                $head_tag = get_echo( 'rsd_link' );
    147147                $html     = $this->get_sample_html_string( $head_tag );
    148                 $this->assertTrue( wp_is_owned_html_output( $html ) );
     148                $this->assertTrue( wp_is_local_html_output( $html ) );
    149149
    150150                // HTML includes modified RSD link but same URL.
    151151                $head_tag = str_replace( ' />', '>', get_echo( 'rsd_link' ) );
    152152                $html     = $this->get_sample_html_string( $head_tag );
    153                 $this->assertTrue( wp_is_owned_html_output( $html ) );
     153                $this->assertTrue( wp_is_local_html_output( $html ) );
    154154
    155155                // HTML does not include RSD link.
    156156                $html = $this->get_sample_html_string();
    157                 $this->assertFalse( wp_is_owned_html_output( $html ) );
    158         }
    159 
    160         /**
    161          * @ticket 47577
    162          */
    163         public function test_wp_is_owned_html_output_via_wlwmanifest_link() {
     157                $this->assertFalse( wp_is_local_html_output( $html ) );
     158        }
     159
     160        /**
     161         * @ticket 47577
     162         */
     163        public function test_wp_is_local_html_output_via_wlwmanifest_link() {
    164164                remove_action( 'wp_head', 'rsd_link' );
    165165
     
    167167                $head_tag = get_echo( 'wlwmanifest_link' );
    168168                $html     = $this->get_sample_html_string( $head_tag );
    169                 $this->assertTrue( wp_is_owned_html_output( $html ) );
     169                $this->assertTrue( wp_is_local_html_output( $html ) );
    170170
    171171                // HTML includes modified WLW manifest link but same URL.
    172172                $head_tag = str_replace( ' />', '>', get_echo( 'wlwmanifest_link' ) );
    173173                $html     = $this->get_sample_html_string( $head_tag );
    174                 $this->assertTrue( wp_is_owned_html_output( $html ) );
     174                $this->assertTrue( wp_is_local_html_output( $html ) );
    175175
    176176                // HTML includes WLW manifest link with alternative URL scheme.
     
    178178                $head_tag = false !== strpos( $head_tag, 'https://' ) ? str_replace( 'https://', 'http://', $head_tag ) : str_replace( 'http://', 'https://', $head_tag );
    179179                $html     = $this->get_sample_html_string( $head_tag );
    180                 $this->assertTrue( wp_is_owned_html_output( $html ) );
     180                $this->assertTrue( wp_is_local_html_output( $html ) );
    181181
    182182                // HTML does not include WLW manifest link.
    183183                $html = $this->get_sample_html_string();
    184                 $this->assertFalse( wp_is_owned_html_output( $html ) );
    185         }
    186 
    187         /**
    188          * @ticket 47577
    189          */
    190         public function test_wp_is_owned_html_output_via_rest_link() {
     184                $this->assertFalse( wp_is_local_html_output( $html ) );
     185        }
     186
     187        /**
     188         * @ticket 47577
     189         */
     190        public function test_wp_is_local_html_output_via_rest_link() {
    191191                remove_action( 'wp_head', 'rsd_link' );
    192192                remove_action( 'wp_head', 'wlwmanifest_link' );
     
    195195                $head_tag = get_echo( 'rest_output_link_wp_head' );
    196196                $html     = $this->get_sample_html_string( $head_tag );
    197                 $this->assertTrue( wp_is_owned_html_output( $html ) );
     197                $this->assertTrue( wp_is_local_html_output( $html ) );
    198198
    199199                // HTML includes modified REST API link but same URL.
    200200                $head_tag = str_replace( ' />', '>', get_echo( 'rest_output_link_wp_head' ) );
    201201                $html     = $this->get_sample_html_string( $head_tag );
    202                 $this->assertTrue( wp_is_owned_html_output( $html ) );
     202                $this->assertTrue( wp_is_local_html_output( $html ) );
    203203
    204204                // HTML includes REST API link with alternative URL scheme.
     
    206206                $head_tag = false !== strpos( $head_tag, 'https://' ) ? str_replace( 'https://', 'http://', $head_tag ) : str_replace( 'http://', 'https://', $head_tag );
    207207                $html     = $this->get_sample_html_string( $head_tag );
    208                 $this->assertTrue( wp_is_owned_html_output( $html ) );
     208                $this->assertTrue( wp_is_local_html_output( $html ) );
    209209
    210210                // HTML does not include REST API link.
    211211                $html = $this->get_sample_html_string();
    212                 $this->assertFalse( wp_is_owned_html_output( $html ) );
    213         }
    214 
    215         /**
    216          * @ticket 47577
    217          */
    218         public function test_wp_is_owned_html_output_cannot_determine() {
     212                $this->assertFalse( wp_is_local_html_output( $html ) );
     213        }
     214
     215        /**
     216         * @ticket 47577
     217         */
     218        public function test_wp_is_local_html_output_cannot_determine() {
    219219                remove_action( 'wp_head', 'rsd_link' );
    220220                remove_action( 'wp_head', 'wlwmanifest_link' );
     
    223223                // The HTML here doesn't matter because all hooks are removed.
    224224                $html = $this->get_sample_html_string();
    225                 $this->assertNull( wp_is_owned_html_output( $html ) );
     225                $this->assertNull( wp_is_local_html_output( $html ) );
    226226        }
    227227
  • trunk/tests/phpunit/tests/rest-api/rest-schema-setup.php

    r50065 r50072  
    138138                        '/wp-site-health/v1/tests/background-updates',
    139139                        '/wp-site-health/v1/tests/loopback-requests',
     140                        '/wp-site-health/v1/tests/https-status',
    140141                        '/wp-site-health/v1/tests/dotorg-communication',
    141142                        '/wp-site-health/v1/tests/authorization-header',
  • trunk/tests/qunit/fixtures/wp-api-generated.js

    r50065 r50072  
    61886188                    {
    61896189                        "href": "http://example.org/index.php?rest_route=/wp-site-health/v1/tests/loopback-requests"
     6190                    }
     6191                ]
     6192            }
     6193        },
     6194        "/wp-site-health/v1/tests/https-status": {
     6195            "namespace": "wp-site-health/v1",
     6196            "methods": [
     6197                "GET"
     6198            ],
     6199            "endpoints": [
     6200                {
     6201                    "methods": [
     6202                        "GET"
     6203                    ],
     6204                    "args": []
     6205                }
     6206            ],
     6207            "_links": {
     6208                "self": [
     6209                    {
     6210                        "href": "http://example.org/index.php?rest_route=/wp-site-health/v1/tests/https-status"
    61906211                    }
    61916212                ]
Note: See TracChangeset for help on using the changeset viewer.