Index: src/wp-admin/includes/class-wp-site-health.php
===================================================================
--- src/wp-admin/includes/class-wp-site-health.php	(revision 45550)
+++ src/wp-admin/includes/class-wp-site-health.php	(working copy)
@@ -1272,7 +1272,7 @@
 	 */
 	public function get_test_https_status() {
 		$result = array(
-			'label'       => __( 'Your website is using an active HTTPS connection.' ),
+			'label'       => __( 'Your website is using an active HTTPS connection' ),
 			'status'      => 'good',
 			'badge'       => array(
 				'label' => __( 'Security' ),
@@ -1293,34 +1293,38 @@
 			'test'        => 'https_status',
 		);
 
-		if ( is_ssl() ) {
-			$wp_url   = get_bloginfo( 'wpurl' );
-			$site_url = get_bloginfo( 'url' );
+		if ( ! wp_is_using_https() ) {
+			$result['status'] = 'recommended';
 
-			if ( 'https' !== substr( $wp_url, 0, 5 ) || 'https' !== substr( $site_url, 0, 5 ) ) {
-				$result['status'] = 'recommended';
+			$result['label'] = __( 'Your website does not use HTTPS' );
 
-				$result['label'] = __( 'Only parts of your site are using HTTPS' );
-
+			if ( is_ssl() ) {
 				$result['description'] = sprintf(
 					'<p>%s</p>',
+					__( 'You are accessing your site with HTTPS, but your site is not correctly configured to use HTTPS.' )
+				);
+			} else {
+				$result['description'] = sprintf(
+					'<p>%s</p>',
+					__( 'Your site is not correctly configured to use HTTPS.' )
+				);
+			}
+
+			if ( wp_is_https_supported() ) {
+				$result['description'] .= sprintf(
+					'<p>%s</p>',
 					sprintf(
 						/* translators: %s: URL to Settings > General to change options. */
-						__( 'You are accessing this website using HTTPS, but your <a href="%s">WordPress Address</a> is not set up to use HTTPS by default.' ),
+						__( 'HTTPS is supported for your website, so you should update your <a href="%s">WordPress Address</a> to use HTTPS by default.' ),
 						esc_url( admin_url( 'options-general.php' ) )
 					)
 				);
-
-				$result['actions'] .= sprintf(
-					'<p><a href="%s">%s</a></p>',
-					esc_url( admin_url( 'options-general.php' ) ),
-					__( 'Update your site addresses' )
+			} else {
+				$result['description'] .= sprintf(
+					'<p>%s</p>',
+					__( 'Talk to your web host about supporting HTTPS for your website.' )
 				);
 			}
-		} else {
-			$result['status'] = 'recommended';
-
-			$result['label'] = __( 'Your site does not use HTTPS' );
 		}
 
 		return $result;
Index: src/wp-includes/default-filters.php
===================================================================
--- src/wp-includes/default-filters.php	(revision 45550)
+++ src/wp-includes/default-filters.php	(working copy)
@@ -332,6 +332,13 @@
 	add_action( 'init', 'wp_cron' );
 }
 
+// HTTPS detection
+add_action( 'init', 'wp_cron_schedule_https_detection' );
+add_action( 'wp_https_detection', 'wp_update_https_detection_errors' );
+add_filter( 'cron_request', 'wp_cron_conditionally_prevent_sslverify', 9999 );
+add_filter( 'the_content', 'wp_replace_insecure_self_links' );
+add_filter( 'widget_text', 'wp_replace_insecure_self_links' );
+
 // 2 Actions 2 Furious
 add_action( 'do_feed_rdf', 'do_feed_rdf', 10, 1 );
 add_action( 'do_feed_rss', 'do_feed_rss', 10, 1 );
Index: src/wp-includes/https-detection.php
===================================================================
--- src/wp-includes/https-detection.php	(nonexistent)
+++ src/wp-includes/https-detection.php	(working copy)
@@ -0,0 +1,149 @@
+<?php
+/**
+ * HTTPS detection functions.
+ *
+ * @package WordPress
+ * @since 5.4.0
+ */
+
+/**
+ * Checks whether the website is using HTTPS.
+ *
+ * This is based on whether the home and site URL are using HTTPS.
+ *
+ * @since 5.4.0
+ *
+ * @return bool True if using HTTPS, false otherwise.
+ */
+function wp_is_using_https() {
+	if ( 'https' !== wp_parse_url( home_url(), PHP_URL_SCHEME ) ) {
+		return false;
+	}
+
+	if ( 'https' !== wp_parse_url( site_url(), PHP_URL_SCHEME ) ) {
+		return false;
+	}
+
+	return true;
+}
+
+/**
+ * Checks whether HTTPS is supported for the server and domain.
+ *
+ * @since 5.4.0
+ *
+ * @return bool True if HTTPS is supported, false otherwise.
+ */
+function wp_is_https_supported() {
+	$https_detection_errors = get_option( 'https_detection_errors' );
+
+	// If option has never been set by the Cron hook before, run it on-the-fly as fallback.
+	if ( false === $https_detection_errors ) {
+		wp_update_https_detection_errors();
+
+		$https_detection_errors = get_option( 'https_detection_errors' );
+	}
+
+	// If there are no detection errors, HTTPS is supported.
+	return empty( $https_detection_errors );
+}
+
+/**
+ * Runs a remote HTTPS request to detect whether HTTPS supported, and stores potential errors.
+ *
+ * This internal function is called by a regular Cron hook to ensure HTTPS support is detected and maintained.
+ *
+ * @since 5.4.0
+ * @access private
+ */
+function wp_update_https_detection_errors() {
+	$support_errors = new WP_Error();
+
+	$response = wp_remote_request(
+		home_url( '/', 'https' ),
+		array(
+			'headers'   => array(
+				'Cache-Control' => 'no-cache',
+			),
+			'sslverify' => true,
+		)
+	);
+
+	if ( is_wp_error( $response ) ) {
+		$unverified_response = wp_remote_request(
+			home_url( '/', 'https' ),
+			array(
+				'headers'   => array(
+					'Cache-Control' => 'no-cache',
+				),
+				'sslverify' => false,
+			)
+		);
+
+		if ( is_wp_error( $unverified_response ) ) {
+			$support_errors->add(
+				$unverified_response->get_error_code(),
+				$unverified_response->get_error_message()
+			);
+		} else {
+			$support_errors->add(
+				'ssl_verification_failed',
+				$response->get_error_message()
+			);
+		}
+
+		$response = $unverified_response;
+	}
+
+	if ( ! is_wp_error( $response ) && 200 !== wp_remote_retrieve_response_code( $response ) ) {
+		$support_errors->add( 'response_error', wp_remote_retrieve_response_message( $response ) );
+	}
+
+	update_option( 'https_detection_errors', $support_errors->errors );
+}
+
+/**
+ * Schedules the Cron hook for detecting HTTPS support.
+ *
+ * @since 5.4.0
+ * @access private
+ */
+function wp_cron_schedule_https_detection() {
+	if ( ! wp_next_scheduled( 'wp_https_detection' ) ) {
+		wp_schedule_event( time(), 'twicedaily', 'wp_https_detection' );
+	}
+}
+
+/**
+ * Disables SSL verification if the 'cron_request' arguments include an HTTPS URL.
+ *
+ * This prevents an issue if HTTPS breaks, where there would be a failed attempt to verify HTTPS.
+ *
+ * @since 5.4.0
+ * @access private
+ *
+ * @param array $request The Cron request arguments.
+ * @return array $request The filtered Cron request arguments.
+ */
+function wp_cron_conditionally_prevent_sslverify( $request ) {
+	if ( 'https' === wp_parse_url( $request['url'], PHP_URL_SCHEME ) ) {
+		$request['args']['sslverify'] = false;
+	}
+	return $request;
+}
+
+/**
+ * Replaces insecure HTTP URLs with HTTPS URLs in the given content.
+ *
+ * @since 5.4.0
+ *
+ * @param string $content Content to replace insecure URLs in.
+ * @return string Modified content.
+ */
+function wp_replace_insecure_self_links( $content ) {
+	if ( ! wp_is_using_https() ) {
+		return $content;
+	}
+
+	return str_replace( home_url( '', 'http' ), home_url( '', 'https' ), $content );
+}
Index: src/wp-settings.php
===================================================================
--- src/wp-settings.php	(revision 45550)
+++ src/wp-settings.php	(working copy)
@@ -167,6 +167,7 @@
 require( ABSPATH . WPINC . '/theme.php' );
 require( ABSPATH . WPINC . '/class-wp-theme.php' );
 require( ABSPATH . WPINC . '/template.php' );
+require( ABSPATH . WPINC . '/https-detection.php' );
 require( ABSPATH . WPINC . '/class-wp-user-request.php' );
 require( ABSPATH . WPINC . '/user.php' );
 require( ABSPATH . WPINC . '/class-wp-user-query.php' );
