Commit dd21bf5f22 for wordpress.org

commit dd21bf5f2274e457d817d68511991b447898d054
Author: Peter Wilson <wilson@peterwilson.cc>
Date:   Sat Jul 27 00:27:16 2024 +0000

    General: Introduce `wp_get_wp_version()` to get unmodified version.

    Introduces `wp_get_wp_version()` to get an unmodified value of `$wp_version` from `wp-includes/version.php`. Some plugins modify the global in an attempt to improve security through obscurity. This practice can cause errors in WordPress so the ability to get an unmodified version is needed.

    Replaces instances within the code base in which `version.php` was required in order to get an unmodified value. `script-loader.php` is intentionally excluded from the replacements as the function is not always available to the file.

    Props debarghyabanerjee, afragen, costdev.
    See #61627.


    Built from https://develop.svn.wordpress.org/trunk@58813


    git-svn-id: http://core.svn.wordpress.org/trunk@58209 1a063a9b-81f0-0310-95a4-ce76da25c4cd

diff --git a/wp-admin/includes/credits.php b/wp-admin/includes/credits.php
index 907ee93c0b..1ad2a37c2b 100644
--- a/wp-admin/includes/credits.php
+++ b/wp-admin/includes/credits.php
@@ -19,10 +19,7 @@
  */
 function wp_credits( $version = '', $locale = '' ) {
 	if ( ! $version ) {
-		// Include an unmodified $wp_version.
-		require ABSPATH . WPINC . '/version.php';
-
-		$version = $wp_version;
+		$version = wp_get_wp_version();
 	}

 	if ( ! $locale ) {
diff --git a/wp-admin/includes/dashboard.php b/wp-admin/includes/dashboard.php
index 2aeaa24e46..022a00174c 100644
--- a/wp-admin/includes/dashboard.php
+++ b/wp-admin/includes/dashboard.php
@@ -1819,13 +1819,10 @@ function wp_check_browser_version() {
 	$response = get_site_transient( 'browser_' . $key );

 	if ( false === $response ) {
-		// Include an unmodified $wp_version.
-		require ABSPATH . WPINC . '/version.php';
-
 		$url     = 'http://api.wordpress.org/core/browse-happy/1.1/';
 		$options = array(
 			'body'       => array( 'useragent' => $_SERVER['HTTP_USER_AGENT'] ),
-			'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url( '/' ),
+			'user-agent' => 'WordPress/' . wp_get_wp_version() . '; ' . home_url( '/' ),
 		);

 		if ( wp_http_supports( array( 'ssl' ) ) ) {
diff --git a/wp-admin/includes/import.php b/wp-admin/includes/import.php
index 87ee00e5f7..530045894c 100644
--- a/wp-admin/includes/import.php
+++ b/wp-admin/includes/import.php
@@ -136,22 +136,19 @@ function wp_import_handle_upload() {
  * @return array Importers with metadata for each.
  */
 function wp_get_popular_importers() {
-	// Include an unmodified $wp_version.
-	require ABSPATH . WPINC . '/version.php';
-
 	$locale            = get_user_locale();
-	$cache_key         = 'popular_importers_' . md5( $locale . $wp_version );
+	$cache_key         = 'popular_importers_' . md5( $locale . wp_get_wp_version() );
 	$popular_importers = get_site_transient( $cache_key );

 	if ( ! $popular_importers ) {
 		$url     = add_query_arg(
 			array(
 				'locale'  => $locale,
-				'version' => $wp_version,
+				'version' => wp_get_wp_version(),
 			),
 			'http://api.wordpress.org/core/importers/1.1/'
 		);
-		$options = array( 'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url( '/' ) );
+		$options = array( 'user-agent' => 'WordPress/' . wp_get_wp_version() . '; ' . home_url( '/' ) );

 		if ( wp_http_supports( array( 'ssl' ) ) ) {
 			$url = set_url_scheme( $url, 'https' );
diff --git a/wp-admin/includes/plugin-install.php b/wp-admin/includes/plugin-install.php
index 59537e21df..38c4b50e7d 100644
--- a/wp-admin/includes/plugin-install.php
+++ b/wp-admin/includes/plugin-install.php
@@ -100,9 +100,6 @@
  *         for more information on the make-up of possible return values depending on the value of `$action`.
  */
 function plugins_api( $action, $args = array() ) {
-	// Include an unmodified $wp_version.
-	require ABSPATH . WPINC . '/version.php';
-
 	if ( is_array( $args ) ) {
 		$args = (object) $args;
 	}
@@ -118,7 +115,7 @@ function plugins_api( $action, $args = array() ) {
 	}

 	if ( ! isset( $args->wp_version ) ) {
-		$args->wp_version = substr( $wp_version, 0, 3 ); // x.y
+		$args->wp_version = substr( wp_get_wp_version(), 0, 3 ); // x.y
 	}

 	/**
@@ -168,7 +165,7 @@ function plugins_api( $action, $args = array() ) {

 		$http_args = array(
 			'timeout'    => 15,
-			'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url( '/' ),
+			'user-agent' => 'WordPress/' . wp_get_wp_version() . '; ' . home_url( '/' ),
 		);
 		$request   = wp_remote_get( $url, $http_args );

diff --git a/wp-admin/includes/theme.php b/wp-admin/includes/theme.php
index 64ef380fc4..8fc9c00f14 100644
--- a/wp-admin/includes/theme.php
+++ b/wp-admin/includes/theme.php
@@ -493,9 +493,6 @@ function get_theme_feature_list( $api = true ) {
  *         for more information on the make-up of possible return objects depending on the value of `$action`.
  */
 function themes_api( $action, $args = array() ) {
-	// Include an unmodified $wp_version.
-	require ABSPATH . WPINC . '/version.php';
-
 	if ( is_array( $args ) ) {
 		$args = (object) $args;
 	}
@@ -511,7 +508,7 @@ function themes_api( $action, $args = array() ) {
 	}

 	if ( ! isset( $args->wp_version ) ) {
-		$args->wp_version = substr( $wp_version, 0, 3 ); // x.y
+		$args->wp_version = substr( wp_get_wp_version(), 0, 3 ); // x.y
 	}

 	/**
@@ -562,7 +559,7 @@ function themes_api( $action, $args = array() ) {

 		$http_args = array(
 			'timeout'    => 15,
-			'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url( '/' ),
+			'user-agent' => 'WordPress/' . wp_get_wp_version() . '; ' . home_url( '/' ),
 		);
 		$request   = wp_remote_get( $url, $http_args );

diff --git a/wp-admin/includes/translation-install.php b/wp-admin/includes/translation-install.php
index ef9fcc6065..f18bbecd9c 100644
--- a/wp-admin/includes/translation-install.php
+++ b/wp-admin/includes/translation-install.php
@@ -17,9 +17,6 @@
  * @return array|WP_Error On success an associative array of translations, WP_Error on failure.
  */
 function translations_api( $type, $args = null ) {
-	// Include an unmodified $wp_version.
-	require ABSPATH . WPINC . '/version.php';
-
 	if ( ! in_array( $type, array( 'plugins', 'themes', 'core' ), true ) ) {
 		return new WP_Error( 'invalid_type', __( 'Invalid translation type.' ) );
 	}
@@ -46,7 +43,7 @@ function translations_api( $type, $args = null ) {
 		$options = array(
 			'timeout' => 3,
 			'body'    => array(
-				'wp_version' => $wp_version,
+				'wp_version' => wp_get_wp_version(),
 				'locale'     => get_locale(),
 				'version'    => $args['version'], // Version of plugin, theme or core.
 			),
@@ -128,10 +125,7 @@ function wp_get_available_translations() {
 		}
 	}

-	// Include an unmodified $wp_version.
-	require ABSPATH . WPINC . '/version.php';
-
-	$api = translations_api( 'core', array( 'version' => $wp_version ) );
+	$api = translations_api( 'core', array( 'version' => wp_get_wp_version() ) );

 	if ( is_wp_error( $api ) || empty( $api['translations'] ) ) {
 		return array();
diff --git a/wp-admin/includes/update.php b/wp-admin/includes/update.php
index 312289f78e..629c1be1cc 100644
--- a/wp-admin/includes/update.php
+++ b/wp-admin/includes/update.php
@@ -264,10 +264,7 @@ function core_update_footer( $msg = '' ) {
 		$cur->response = '';
 	}

-	// Include an unmodified $wp_version.
-	require ABSPATH . WPINC . '/version.php';
-
-	$is_development_version = preg_match( '/alpha|beta|RC/', $wp_version );
+	$is_development_version = preg_match( '/alpha|beta|RC/', wp_get_wp_version() );

 	if ( $is_development_version ) {
 		return sprintf(
@@ -854,8 +851,6 @@ function wp_theme_update_row( $theme_key, $theme ) {
  * @return void|false
  */
 function maintenance_nag() {
-	// Include an unmodified $wp_version.
-	require ABSPATH . WPINC . '/version.php';
 	global $upgrading;

 	$nag = isset( $upgrading );
@@ -873,7 +868,7 @@ function maintenance_nag() {
 		 * This flag is cleared whenever a successful update occurs using Core_Upgrader.
 		 */
 		$comparison = ! empty( $failed['critical'] ) ? '>=' : '>';
-		if ( isset( $failed['attempted'] ) && version_compare( $failed['attempted'], $wp_version, $comparison ) ) {
+		if ( isset( $failed['attempted'] ) && version_compare( $failed['attempted'], wp_get_wp_version(), $comparison ) ) {
 			$nag = true;
 		}
 	}
diff --git a/wp-includes/functions.php b/wp-includes/functions.php
index e821f6f2b0..91afbecf96 100644
--- a/wp-includes/functions.php
+++ b/wp-includes/functions.php
@@ -9006,3 +9006,21 @@ function wp_admin_notice( $message, $args = array() ) {

 	echo wp_kses_post( wp_get_admin_notice( $message, $args ) );
 }
+
+/**
+ * Returns the current WordPress Version.
+ *
+ * Returns an unmodified version of `$wp_version`. Some plugins modify the
+ * global in an attempt to improve security through obscurity. This
+ * practice can cause errors in WordPress so the ability to get an
+ * unmodified version is needed.
+ *
+ * @since 6.7.0
+ *
+ * @return string The current WordPress Version.
+ */
+function wp_get_wp_version() {
+	require ABSPATH . WPINC . '/version.php';
+
+	return $wp_version;
+}
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php
index 41f37c9f1d..3345ea0aa1 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php
@@ -87,13 +87,6 @@ class WP_REST_Pattern_Directory_Controller extends WP_REST_Controller {
 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 	 */
 	public function get_items( $request ) {
-		/*
-		 * Include an unmodified `$wp_version`, so the API can craft a response that's tailored to
-		 * it. Some plugins modify the version in a misguided attempt to improve security by
-		 * obscuring the version, which can cause invalid requests.
-		 */
-		require ABSPATH . WPINC . '/version.php';
-
 		$valid_query_args = array(
 			'offset'   => true,
 			'order'    => true,
@@ -106,7 +99,7 @@ class WP_REST_Pattern_Directory_Controller extends WP_REST_Controller {
 		$query_args       = array_intersect_key( $request->get_params(), $valid_query_args );

 		$query_args['locale']             = get_user_locale();
-		$query_args['wp-version']         = $wp_version;
+		$query_args['wp-version']         = wp_get_wp_version();
 		$query_args['pattern-categories'] = isset( $request['category'] ) ? $request['category'] : false;
 		$query_args['pattern-keywords']   = isset( $request['keyword'] ) ? $request['keyword'] : false;

diff --git a/wp-includes/script-loader.php b/wp-includes/script-loader.php
index b73f12b9cc..121adc646e 100644
--- a/wp-includes/script-loader.php
+++ b/wp-includes/script-loader.php
@@ -684,7 +684,13 @@ function wp_scripts_get_suffix( $type = '' ) {
 	static $suffixes;

 	if ( null === $suffixes ) {
-		// Include an unmodified $wp_version.
+		/*
+		 * Include an unmodified $wp_version.
+		 *
+		 * Note: wp_get_wp_version() is not used here, as this file can be included
+		 * via wp-admin/load-scripts.php or wp-admin/load-styles.php, in which case
+		 * wp-includes/functions.php is not loaded.
+		 */
 		require ABSPATH . WPINC . '/version.php';

 		/*
@@ -1522,7 +1528,13 @@ function wp_default_scripts( $scripts ) {
 function wp_default_styles( $styles ) {
 	global $editor_styles;

-	// Include an unmodified $wp_version.
+	/*
+	 * Include an unmodified $wp_version.
+	 *
+	 * Note: wp_get_wp_version() is not used here, as this file can be included
+	 * via wp-admin/load-scripts.php or wp-admin/load-styles.php, in which case
+	 * wp-includes/functions.php is not loaded.
+	 */
 	require ABSPATH . WPINC . '/version.php';

 	if ( ! defined( 'SCRIPT_DEBUG' ) ) {
diff --git a/wp-includes/update.php b/wp-includes/update.php
index d521913bb9..f8aa27bd8d 100644
--- a/wp-includes/update.php
+++ b/wp-includes/update.php
@@ -31,22 +31,20 @@ function wp_version_check( $extra_stats = array(), $force_check = false ) {
 		return;
 	}

-	// Include an unmodified $wp_version.
-	require ABSPATH . WPINC . '/version.php';
 	$php_version = PHP_VERSION;

 	$current      = get_site_transient( 'update_core' );
 	$translations = wp_get_installed_translations( 'core' );

 	// Invalidate the transient when $wp_version changes.
-	if ( is_object( $current ) && $wp_version !== $current->version_checked ) {
+	if ( is_object( $current ) && wp_get_wp_version() !== $current->version_checked ) {
 		$current = false;
 	}

 	if ( ! is_object( $current ) ) {
 		$current                  = new stdClass();
 		$current->updates         = array();
-		$current->version_checked = $wp_version;
+		$current->version_checked = wp_get_wp_version();
 	}

 	if ( ! empty( $extra_stats ) ) {
@@ -95,7 +93,7 @@ function wp_version_check( $extra_stats = array(), $force_check = false ) {
 	$extensions = get_loaded_extensions();
 	sort( $extensions, SORT_STRING | SORT_FLAG_CASE );
 	$query = array(
-		'version'            => $wp_version,
+		'version'            => wp_get_wp_version(),
 		'php'                => $php_version,
 		'locale'             => $locale,
 		'mysql'              => $mysql_version,
@@ -191,7 +189,7 @@ function wp_version_check( $extra_stats = array(), $force_check = false ) {

 	$options = array(
 		'timeout'    => $doing_cron ? 30 : 3,
-		'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url( '/' ),
+		'user-agent' => 'WordPress/' . wp_get_wp_version() . '; ' . home_url( '/' ),
 		'headers'    => array(
 			'wp_install' => $wp_install,
 			'wp_blog'    => home_url( '/' ),
@@ -266,7 +264,7 @@ function wp_version_check( $extra_stats = array(), $force_check = false ) {
 	$updates                  = new stdClass();
 	$updates->updates         = $offers;
 	$updates->last_checked    = time();
-	$updates->version_checked = $wp_version;
+	$updates->version_checked = wp_get_wp_version();

 	if ( isset( $body['translations'] ) ) {
 		$updates->translations = $body['translations'];
@@ -315,9 +313,6 @@ function wp_update_plugins( $extra_stats = array() ) {
 		return;
 	}

-	// Include an unmodified $wp_version.
-	require ABSPATH . WPINC . '/version.php';
-
 	// If running blog-side, bail unless we've not checked in the last 12 hours.
 	if ( ! function_exists( 'get_plugins' ) ) {
 		require_once ABSPATH . 'wp-admin/includes/plugin.php';
@@ -423,7 +418,7 @@ function wp_update_plugins( $extra_stats = array() ) {
 			'locale'       => wp_json_encode( $locales ),
 			'all'          => wp_json_encode( true ),
 		),
-		'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url( '/' ),
+		'user-agent' => 'WordPress/' . wp_get_wp_version() . '; ' . home_url( '/' ),
 	);

 	if ( $extra_stats ) {
@@ -590,9 +585,6 @@ function wp_update_themes( $extra_stats = array() ) {
 		return;
 	}

-	// Include an unmodified $wp_version.
-	require ABSPATH . WPINC . '/version.php';
-
 	$installed_themes = wp_get_themes();
 	$translations     = wp_get_installed_translations( 'themes' );

@@ -705,7 +697,7 @@ function wp_update_themes( $extra_stats = array() ) {
 			'translations' => wp_json_encode( $translations ),
 			'locale'       => wp_json_encode( $locales ),
 		),
-		'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url( '/' ),
+		'user-agent' => 'WordPress/' . wp_get_wp_version() . '; ' . home_url( '/' ),
 	);

 	if ( $extra_stats ) {
@@ -989,14 +981,11 @@ function wp_get_update_data() {
  * @global string $wp_version The WordPress version string.
  */
 function _maybe_update_core() {
-	// Include an unmodified $wp_version.
-	require ABSPATH . WPINC . '/version.php';
-
 	$current = get_site_transient( 'update_core' );

 	if ( isset( $current->last_checked, $current->version_checked )
 		&& 12 * HOUR_IN_SECONDS > ( time() - $current->last_checked )
-		&& $current->version_checked === $wp_version
+		&& wp_get_wp_version() === $current->version_checked
 	) {
 		return;
 	}
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 5877f19465..c594ee2975 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '6.7-alpha-58812';
+$wp_version = '6.7-alpha-58813';

 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.