Skip to content

Commit

Permalink
General: Introduce wp_get_wp_version() to get unmodified version.
Browse files Browse the repository at this point in the history
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.



git-svn-id: https://develop.svn.wordpress.org/trunk@58813 602fd350-edb4-49c9-b593-d223f7449a82
  • Loading branch information
peterwilsoncc committed Jul 27, 2024
1 parent ed59f77 commit c41304d
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 68 deletions.
5 changes: 1 addition & 4 deletions src/wp-admin/includes/credits.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) {
Expand Down
5 changes: 1 addition & 4 deletions src/wp-admin/includes/dashboard.php
Original file line number Diff line number Diff line change
Expand Up @@ -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' ) ) ) {
Expand Down
9 changes: 3 additions & 6 deletions src/wp-admin/includes/import.php
Original file line number Diff line number Diff line change
Expand Up @@ -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' );
Expand Down
7 changes: 2 additions & 5 deletions src/wp-admin/includes/plugin-install.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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
}

/**
Expand Down Expand Up @@ -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 );

Expand Down
7 changes: 2 additions & 5 deletions src/wp-admin/includes/theme.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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
}

/**
Expand Down Expand Up @@ -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 );

Expand Down
10 changes: 2 additions & 8 deletions src/wp-admin/includes/translation-install.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.' ) );
}
Expand All @@ -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.
),
Expand Down Expand Up @@ -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();
Expand Down
9 changes: 2 additions & 7 deletions src/wp-admin/includes/update.php
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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 );
Expand All @@ -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;
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/wp-includes/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,6 @@ public function get_items_permissions_check( $request ) {
* @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,
Expand All @@ -106,7 +99,7 @@ public function get_items( $request ) {
$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;

Expand Down
16 changes: 14 additions & 2 deletions src/wp-includes/script-loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';

/*
Expand Down Expand Up @@ -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' ) ) {
Expand Down
27 changes: 8 additions & 19 deletions src/wp-includes/update.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) ) {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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( '/' ),
Expand Down Expand Up @@ -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'];
Expand Down Expand Up @@ -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';
Expand Down Expand Up @@ -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 ) {
Expand Down Expand Up @@ -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' );

Expand Down Expand Up @@ -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 ) {
Expand Down Expand Up @@ -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;
}
Expand Down
34 changes: 34 additions & 0 deletions tests/phpunit/tests/functions/wpGetWpVersion.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

/**
* Tests for wp_get_wp_version().
*
* @group functions
*
* @covers ::wp_get_wp_version
*/
class Tests_Functions_WpGetWpVersion extends WP_UnitTestCase {

/**
* Tests that the WordPress version is returned.
*
* @ticket 61627
*/
public function test_should_return_wp_version() {
$this->assertSame( $GLOBALS['wp_version'], wp_get_wp_version() );
}

/**
* Tests that changes to the `$wp_version` global are ignored.
*
* @ticket 61627
*/
public function test_should_ignore_changes_to_wp_version_global() {
$original_wp_version = $GLOBALS['wp_version'];
$GLOBALS['wp_version'] = 'modified_wp_version';
$actual = wp_get_wp_version();
$GLOBALS['wp_version'] = $original_wp_version;

$this->assertSame( $original_wp_version, $actual );
}
}

0 comments on commit c41304d

Please sign in to comment.