Skip to content

Commit

Permalink
Merge branch 'develop' into trunk
Browse files Browse the repository at this point in the history
  • Loading branch information
felipeelia committed Jun 11, 2024
2 parents 67331ba + a989d9e commit a5ede43
Show file tree
Hide file tree
Showing 23 changed files with 141 additions and 101 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ All notable changes to this project will be documented in this file, per [the Ke
### Security
-->

## [5.1.2] - 2024-06-11

**This is a security release affecting all previous versions of ElasticPress.**

### Security
* Missing nonce verification for the sync triggered during activation of some features. Props [@felipeelia](https://github.com/felipeelia) and [@dhakalananda](https://github.com/dhakalananda) via [#3929](https://github.com/10up/ElasticPress/pull/3929).
* Missing nonce verification for retrying the EP connection and fixed PHPCS linting rules. Props [@felipeelia](https://github.com/felipeelia) via [#3932](https://github.com/10up/ElasticPress/pull/3932).

## [5.1.1] - 2024-05-27

### Changed
Expand Down Expand Up @@ -2115,6 +2123,7 @@ This is a bug fix release with some filter additions.
- Initial plugin release

[Unreleased]: https://github.com/10up/ElasticPress/compare/trunk...develop
[5.1.2]: https://github.com/10up/ElasticPress/compare/5.1.1...5.1.2
[5.1.1]: https://github.com/10up/ElasticPress/compare/5.1.0...5.1.1
[5.1.0]: https://github.com/10up/ElasticPress/compare/5.0.2...5.1.0
[5.0.2]: https://github.com/10up/ElasticPress/compare/5.0.1...5.0.2
Expand Down
1 change: 1 addition & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ Thank you to all the people who have already contributed to this repository via
[Maarten Bruna (@ictbeheer)](https://github.com/ictbeheer),
[Dharmesh Patel (@iamdharmesh)](https://github.com/iamdharmesh),
[Lucas Grzegorczyk (@furai)](https://github.com/furai),
[Ananda Dhakal (@dhakalananda)](https://github.com/dhakalananda),
and
[@qazaqstan2025](https://github.com/qazaqstan2025).

Expand Down
6 changes: 3 additions & 3 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ The following versions of this project are currently being supported with securi

| Version | Supported |
| ------- | ------------------ |
| 4.5.0 | :white_check_mark: |
| <4.4.1 | :x: |
| 5.1.2 | :white_check_mark: |
| <5.1.1 | :x: |

## Reporting a Vulnerability

Expand Down Expand Up @@ -38,5 +38,5 @@ Past security advisories, if any, are listed below.

| Advisory Number | Type | Versions affected | Reported by | Additional Information |
|-----------------|--------------------|:-----------------:|-----------------------|-----------------------------|
| CVE-2024-35684 | CSRF | n/a - 5.1.1 | Patchstack Team | [CVE link](https://www.cve.org/CVERecord?id=CVE-2024-35684) |
| EP-2021-02-11 | CSRF Nonce Bypass | 3.5.2 - 3.5.3 | WordPress.org Plugin Review Team | [WPScan link](https://wpscan.com/vulnerability/ce655810-bd08-4042-ac3d-63def5c76994) |
| - | - | - | - | - |
3 changes: 2 additions & 1 deletion assets/js/features/apps/features.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { __ } from '@wordpress/i18n';
* Internal dependencies.
*/
import { useSettingsScreen } from '../../settings-screen';
import { syncUrl } from '../config';
import { syncUrl, syncNonce } from '../config';
import { useFeatureSettings } from '../provider';
import Feature from '../components/feature';
import Tab from '../components/tab';
Expand Down Expand Up @@ -44,6 +44,7 @@ export default () => {
const url = new URL(syncUrl);

url.searchParams.append('do_sync', 'features');
url.searchParams.append('ep_sync_nonce', syncNonce);

return url.toString();
}, []);
Expand Down
4 changes: 2 additions & 2 deletions assets/js/features/config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Window dependencies.
*/
const { apiUrl, epioLogoUrl, features, indexMeta, settings, settingsDraft, syncUrl } =
const { apiUrl, epioLogoUrl, features, indexMeta, settings, settingsDraft, syncUrl, syncNonce } =
window.epDashboard;

export { apiUrl, epioLogoUrl, features, indexMeta, settings, settingsDraft, syncUrl };
export { apiUrl, epioLogoUrl, features, indexMeta, settings, settingsDraft, syncUrl, syncNonce };
1 change: 1 addition & 0 deletions assets/js/sync/src/utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
export const clearSyncParam = () => {
const url = new URL(document.location.href);
url.searchParams.delete('do_sync');
url.searchParams.delete('ep_sync_nonce');
window.history.replaceState({}, document.title, url);
};

Expand Down
4 changes: 2 additions & 2 deletions elasticpress.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Plugin Name: ElasticPress
* Plugin URI: https://github.com/10up/ElasticPress
* Description: A fast and flexible search and query engine for WordPress.
* Version: 5.1.1
* Version: 5.1.2
* Requires at least: 6.0
* Requires PHP: 7.4
* Author: 10up
Expand Down Expand Up @@ -32,7 +32,7 @@
define( 'EP_URL', plugin_dir_url( __FILE__ ) );
define( 'EP_PATH', plugin_dir_path( __FILE__ ) );
define( 'EP_FILE', plugin_basename( __FILE__ ) );
define( 'EP_VERSION', '5.1.1' );
define( 'EP_VERSION', '5.1.2' );

define( 'EP_PHP_VERSION_MIN', '7.4' );

Expand Down
21 changes: 11 additions & 10 deletions includes/classes/AdminNotices.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,6 @@ protected function process_using_autosuggest_defaults_notice() {
return false;
}

if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) {
$url = admin_url( 'network/admin.php?page=elasticpress&do_sync' );
} else {
$url = admin_url( 'admin.php?page=elasticpress&do_sync' );
}

return [
'html' => sprintf( esc_html__( 'Autosuggest feature is enabled. If documents feature is enabled, your media will also become searchable in the frontend.', 'elasticpress' ) ),
'type' => 'info',
Expand Down Expand Up @@ -177,7 +171,7 @@ protected function process_auto_activate_sync_notice() {
return false;
}

if ( isset( $_GET['do_sync'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
if ( Utils\isset_do_sync_parameter() ) {
return false;
}

Expand Down Expand Up @@ -252,7 +246,7 @@ protected function process_upgrade_sync_notice() {
return false;
}

if ( isset( $_GET['do_sync'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
if ( Utils\isset_do_sync_parameter() ) {
return false;
}

Expand Down Expand Up @@ -316,7 +310,7 @@ protected function process_no_sync_notice() {
return false;
}

if ( isset( $_GET['do_sync'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
if ( Utils\isset_do_sync_parameter() ) {
return false;
}

Expand Down Expand Up @@ -595,10 +589,17 @@ protected function process_host_error_notice() {
$response_error = get_transient( 'ep_es_info_response_error' );
}

$retry_url = add_query_arg(
[
'ep-retry' => 1,
'ep_retry_nonce' => wp_create_nonce( 'ep_retry_nonce' ),
]
);

$html = sprintf(
/* translators: 1. Current URL with retry parameter; 2. Settings Page URL */
__( 'There is a problem with connecting to your Elasticsearch host. ElasticPress can <a href="%1$s">try your host again</a>, or you may need to <a href="%2$s">change your settings</a>.', 'elasticpress' ),
esc_url( add_query_arg( 'ep-retry', 1 ) ),
esc_url( $retry_url ),
esc_url( $url )
);

Expand Down
4 changes: 2 additions & 2 deletions includes/classes/Feature/WooCommerce/Orders.php
Original file line number Diff line number Diff line change
Expand Up @@ -515,9 +515,9 @@ public function __call( $method_name, $arguments ) {

if ( in_array( $method_name, $orders_autosuggest_methods, true ) ) {
_deprecated_function(
"\ElasticPress\Feature\WooCommerce\WooCommerce\Orders::{$method_name}", // phpcs:ignore
"\ElasticPress\Feature\WooCommerce\WooCommerce\Orders::{$method_name}", // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
'4.7.0',
"\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders_autosuggest->{$method_name}()" // phpcs:ignore
"\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders_autosuggest->{$method_name}()" // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
);

if ( $this->woocommerce->orders_autosuggest->is_enabled() && method_exists( $this->woocommerce->orders_autosuggest, $method_name ) ) {
Expand Down
4 changes: 2 additions & 2 deletions includes/classes/Feature/WooCommerce/Products.php
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ public function translate_args_admin_products_list( $query ) {
// WooCommerce unsets the search term right after using it to fetch product IDs. Here we add it back.
$search_term = ! empty( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
if ( ! empty( $search_term ) ) {
$query->set( 's', sanitize_text_field( $search_term ) ); // phpcs:ignore WordPress.Security.NonceVerification
$query->set( 's', sanitize_text_field( $search_term ) );

/**
* Filter the fields used in WooCommerce Admin Product Search.
Expand Down Expand Up @@ -973,7 +973,7 @@ protected function maybe_set_orderby( \WP_Query $query ) {
*/
if ( ! empty( $_GET['orderby'] ) && $query->is_main_query() ) { // phpcs:ignore WordPress.Security.NonceVerification
$orderby = sanitize_text_field( wp_unslash( $_GET['orderby'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
switch ( $orderby ) { // phpcs:ignore WordPress.Security.NonceVerification
switch ( $orderby ) {
case 'popularity':
$query->set( 'orderby', $this->get_orderby_meta_mapping( 'total_sales' ) );
$query->set( 'order', 'DESC' );
Expand Down
2 changes: 1 addition & 1 deletion includes/classes/Installer.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public function calculate_install_status() {

$host = Utils\get_host();

if ( empty( $host ) && empty( $_POST['ep_host'] ) ) { // phpcs:ignore
if ( empty( $host ) && empty( $_POST['ep_host'] ) ) {
$this->install_status = 2;

return;
Expand Down
14 changes: 7 additions & 7 deletions includes/classes/Screen.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,35 +101,35 @@ public function determine_screen() {
$this->screen = 'install';

if ( 'elasticpress' === $_GET['page'] ) {
if ( ! isset( $_GET['install_complete'] ) && ( true === $install_status || isset( $_GET['do_sync'] ) ) ) {
if ( ! isset( $_GET['install_complete'] ) && ( true === $install_status || Utils\isset_do_sync_parameter() ) ) {
if ( Utils\is_top_level_admin_context() ) {
$this->screen = 'dashboard';
} else {
$this->screen = 'weighting';
}
}
} elseif ( 'elasticpress-settings' === $_GET['page'] ) {
if ( true === $install_status || 2 === $install_status || isset( $_GET['do_sync'] ) ) {
if ( true === $install_status || 2 === $install_status || Utils\isset_do_sync_parameter() ) {
$this->screen = 'settings';
}
} elseif ( 'elasticpress-health' === $_GET['page'] ) {
if ( ! isset( $_GET['install_complete'] ) && ( true === $install_status || isset( $_GET['do_sync'] ) ) ) {
if ( ! isset( $_GET['install_complete'] ) && ( true === $install_status || Utils\isset_do_sync_parameter() ) ) {
$this->screen = 'health';
}
} elseif ( 'elasticpress-weighting' === $_GET['page'] ) {
if ( ! isset( $_GET['install_complete'] ) && ( true === $install_status || isset( $_GET['do_sync'] ) ) ) {
if ( ! isset( $_GET['install_complete'] ) && ( true === $install_status || Utils\isset_do_sync_parameter() ) ) {
$this->screen = 'weighting';
}
} elseif ( 'elasticpress-synonyms' === $_GET['page'] ) {
if ( ! isset( $_GET['install_complete'] ) && ( true === $install_status || isset( $_GET['do_sync'] ) ) ) {
if ( ! isset( $_GET['install_complete'] ) && ( true === $install_status || Utils\isset_do_sync_parameter() ) ) {
$this->screen = 'synonyms';
}
} elseif ( 'elasticpress-sync' === $_GET['page'] ) {
if ( ! isset( $_GET['install_complete'] ) && ( true === $install_status || isset( $_GET['do_sync'] ) ) ) {
if ( ! isset( $_GET['install_complete'] ) && ( true === $install_status || Utils\isset_do_sync_parameter() ) ) {
$this->screen = 'sync';
}
} elseif ( 'elasticpress-status-report' === $_GET['page'] ) {
if ( ! isset( $_GET['install_complete'] ) && ( true === $install_status || isset( $_GET['do_sync'] ) ) ) {
if ( ! isset( $_GET['install_complete'] ) && ( true === $install_status || Utils\isset_do_sync_parameter() ) ) {
$this->screen = 'status-report';
}
}
Expand Down
1 change: 1 addition & 0 deletions includes/classes/Screen/Features.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public function admin_enqueue_scripts() {
'settings' => $store->get_feature_settings(),
'settingsDraft' => $store->get_feature_settings_draft(),
'syncUrl' => $sync_url,
'syncNonce' => wp_create_nonce( 'ep_sync_nonce' ),
];

wp_localize_script( 'ep_features_script', 'epDashboard', $data );
Expand Down
4 changes: 2 additions & 2 deletions includes/classes/Screen/Sync.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,14 @@ public function admin_enqueue_scripts() {

$data = [
'apiUrl' => rest_url( 'elasticpress/v1/sync' ),
'autoIndex' => isset( $_GET['do_sync'] ) && ( ! defined( 'EP_DASHBOARD_SYNC' ) || EP_DASHBOARD_SYNC ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended
'autoIndex' => Utils\isset_do_sync_parameter() && ( ! defined( 'EP_DASHBOARD_SYNC' ) || EP_DASHBOARD_SYNC ),
'indexMeta' => Utils\get_indexing_status(),
'indexables' => array_map( fn( $indexable) => [ $indexable->slug, $indexable->labels['plural'] ], $indexables ),
'isEpio' => Utils\is_epio(),
'nonce' => wp_create_nonce( 'wp_rest' ),
'postTypes' => array_map( fn( $post_type ) => [ $post_type, get_post_type_object( $post_type )->labels->name ], $post_types ),
'syncHistory' => $sync_history,
'syncTrigger' => ! empty( $_GET['do_sync'] ) ? sanitize_text_field( wp_unslash( $_GET['do_sync'] ) ) : null, // phpcs:ignore WordPress.Security.NonceVerification.Recommended
'syncTrigger' => Utils\isset_do_sync_parameter() ? sanitize_text_field( wp_unslash( $_GET['do_sync'] ) ) : null, // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
];

wp_localize_script( 'ep_sync_scripts', 'epDash', $data );
Expand Down
2 changes: 1 addition & 1 deletion includes/classes/StatusReport/FailedQueries.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public function get_actions() : array {
* If a nonce is present, clear the logs
*/
protected function maybe_clear_logs() {
if ( empty( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'ep-clear-logged-queries' ) ) { // phpcs:ignore WordPress.Security.NonceVerification
if ( empty( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'ep-clear-logged-queries' ) ) {
return;
}

Expand Down
16 changes: 9 additions & 7 deletions includes/dashboard.php
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ function maybe_skip_install() {
return;
}

if ( empty( $_GET['ep-skip-install'] ) || empty( $_GET['nonce'] ) || ! wp_verify_nonce( sanitize_key( $_GET['nonce'] ), 'ep-skip-install' ) || ! in_array( Screen::factory()->get_current_screen(), [ 'install' ], true ) ) { // phpcs:ignore WordPress.Security.NonceVerification
if ( empty( $_GET['ep-skip-install'] ) || empty( $_GET['nonce'] ) || ! wp_verify_nonce( sanitize_key( $_GET['nonce'] ), 'ep-skip-install' ) || ! in_array( Screen::factory()->get_current_screen(), [ 'install' ], true ) ) {
return;
}

Expand Down Expand Up @@ -221,7 +221,11 @@ function maybe_clear_es_info_cache() {
return;
}

if ( empty( $_GET['ep-retry'] ) && ! in_array( Screen::factory()->get_current_screen(), [ 'dashboard', 'settings', 'install' ], true ) ) { // phpcs:ignore WordPress.Security.NonceVerification
$isset_retry = ! empty( $_GET['ep-retry'] ) &&
! empty( $_GET['ep_retry_nonce'] ) &&
wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['ep_retry_nonce'] ) ), 'ep_retry_nonce' );

if ( ! $isset_retry && ! in_array( Screen::factory()->get_current_screen(), [ 'dashboard', 'settings', 'install' ], true ) ) {
return;
}

Expand All @@ -231,8 +235,8 @@ function maybe_clear_es_info_cache() {
delete_transient( 'ep_es_info' );
}

if ( ! empty( $_GET['ep-retry'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
wp_safe_redirect( remove_query_arg( 'ep-retry' ) );
if ( $isset_retry ) {
wp_safe_redirect( remove_query_arg( [ 'ep-retry', 'ep_retry_nonce' ] ) );
exit();
}
}
Expand Down Expand Up @@ -531,9 +535,7 @@ function action_admin_enqueue_dashboard_scripts() {

wp_set_script_translations( 'ep_dashboard_scripts', 'elasticpress' );

$sync_url = ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) ?
network_admin_url( 'admin.php?page=elasticpress-sync&do_sync' ) :
admin_url( 'admin.php?page=elasticpress-sync&do_sync' );
$sync_url = Utils\get_sync_url( true );

$skip_url = ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) ?
network_admin_url( 'admin.php?page=elasticpress' ) :
Expand Down
12 changes: 11 additions & 1 deletion includes/utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -773,13 +773,23 @@ function get_asset_info( $slug, $attribute = null ) {
function get_sync_url( bool $do_sync = false ) : string {
$page = 'admin.php?page=elasticpress-sync';
if ( $do_sync ) {
$page .= '&do_sync';
$page .= '&do_sync&ep_sync_nonce=' . wp_create_nonce( 'ep_sync_nonce' );
}
return ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) ?
network_admin_url( $page ) :
admin_url( $page );
}

/**
* Check if the `do_sync` parameter is set and the nonce is valid.
*
* @since 5.1.2
* @return boolean
*/
function isset_do_sync_parameter() : bool {
return isset( $_GET['do_sync'] ) && ! empty( $_GET['ep_sync_nonce'] ) && wp_verify_nonce( sanitize_key( $_GET['ep_sync_nonce'] ), 'ep_sync_nonce' );
}

/**
* Generate a common prefix to be used while generating a request ID.
*
Expand Down
Loading

0 comments on commit a5ede43

Please sign in to comment.