diff --git a/CHANGELOG.txt b/CHANGELOG.txt index ee9f912f..59e27b4e 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,4 +1,11 @@ == Changelog == += 7.0.9 - Aug 8, 2026 = +- **WordPress 7.0 compatibility.** The new WordPress version is released. The Ecwid ecommerce shopping cart plugin is ready for the new release — everything works well in your WordPress admin and storefront pages. Feel free to upgrade your site to WordPress 7.0. +- **Plugin code improvements for better security. Ecwid ecommerce shopping cart plugin update recommended.** Thanks to Alexander Jurkschat for responsibly reporting the issue. + += 7.0.8 - Feb 13, 2026 = +- **Plugin code improvements for better security. Ecwid ecommerce shopping cart plugin update recommended.** + = 7.0.7 - Jan 29, 2026 = - **Plugin code improvements for better security. Ecwid ecommerce shopping cart plugin update recommended.** diff --git a/ecwid-shopping-cart.php b/ecwid-shopping-cart.php index 4b3bb5dd..9d9e4cc0 100644 --- a/ecwid-shopping-cart.php +++ b/ecwid-shopping-cart.php @@ -5,7 +5,7 @@ Description: Ecwid by Lightspeed is a full-featured shopping cart. It can be easily integrated with any Wordpress blog and takes less than 5 minutes to set up. Text Domain: ecwid-shopping-cart Author: Ecwid Ecommerce -Version: 7.0.7 +Version: 7.0.10 Author URI: https://go.lightspeedhq.com/ecwid-site License: GPLv2 or later */ @@ -2297,7 +2297,7 @@ function ecwid_admin_post_connect() } else if (!isset($_GET['reconnect'])) { wp_safe_redirect(Ecwid_Admin::get_dashboard_url() . '&oauth=no'); } else { - wp_safe_redirect(Ecwid_Admin::get_dashboard_url() . '&reconnect&connection_error'); + wp_safe_redirect( Ecwid_Admin_Main_Page::get_forced_reconnect_url( '&connection_error' ) ); } exit(); } diff --git a/includes/class-ec-store-admin-access.php b/includes/class-ec-store-admin-access.php index 75e7ad55..ba779a93 100644 --- a/includes/class-ec-store-admin-access.php +++ b/includes/class-ec-store-admin-access.php @@ -31,6 +31,10 @@ public function save_custom_user_profile_fields( $user_id ) { return; } + if ( ! $this->can_grant_access() ) { + return; + } + $user = new WP_User( $user_id ); if ( ! empty( $_POST['ec_store_admin_access'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing diff --git a/includes/class-ecwid-admin-main-page.php b/includes/class-ecwid-admin-main-page.php index d07053c1..06b1d318 100644 --- a/includes/class-ecwid-admin-main-page.php +++ b/includes/class-ecwid-admin-main-page.php @@ -11,8 +11,10 @@ class Ecwid_Admin_Main_Page { const PAGE_HASH_UPGRADE = 'billing:feature=sso&plan=ecwid_venture'; const PAGE_HASH_COMPLETE_REGISTRATION = 'complete-registration'; + const NONCE_RECONNECT = 'ec_forced_reconnect'; + public function do_page() { - if ( self::is_forced_reconnect() ) { + if ( self::is_forced_reconnect() && self::is_verified_reconnect_request() ) { ecwid_update_store_id( ecwid_get_demo_store_id() ); } @@ -175,6 +177,41 @@ public static function is_forced_reconnect() { return isset( $_GET['reconnect'] ); } + /** + * Tells whether the current forced reconnect request is allowed to reset + * the store to the demo one. Guards the destructive part of the flow + * against CSRF: displaying the connect page stays nonce-free, resetting + * the store id does not. + */ + public static function is_verified_reconnect_request() { + if ( ! current_user_can( Ecwid_Admin::get_capability() ) ) { + return false; + } + + if ( ! isset( $_GET['_wpnonce'] ) ) { + return false; + } + + return (bool) wp_verify_nonce( + sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), + self::NONCE_RECONNECT + ); + } + + /** + * Builds a nonce-signed url that forces the reconnect flow. + * + * Returns a raw (unescaped) url, so it is safe to pass to wp_safe_redirect() + * and to javascript. Escape it with esc_url() when printing into markup. + * + * @param string $extra_args optional query string appended to the url, e.g. '&connection_error'. + */ + public static function get_forced_reconnect_url( $extra_args = '' ) { + return Ecwid_Admin::get_dashboard_url() + . '&reconnect' . $extra_args + . '&_wpnonce=' . wp_create_nonce( self::NONCE_RECONNECT ); + } + protected static function _get_upgrade_page_hash() { return 'billing:feature=sso&plan=ecwid_venture'; } diff --git a/includes/class-ecwid-oauth.php b/includes/class-ecwid-oauth.php index 382ff866..a5fa589e 100644 --- a/includes/class-ecwid-oauth.php +++ b/includes/class-ecwid-oauth.php @@ -9,6 +9,8 @@ class Ecwid_OAuth { const OPTION_JUST_CONNECTED = 'ecwid_just_connected'; + const NONCE_DISCONNECT = 'ec_disconnect'; + const SCOPE_READ_CATALOG = 'read_catalog'; const SCOPE_READ_STORE_PROFILE = 'read_store_profile'; const SCOPE_UPDATE_STORE_PROFILE = 'update_store_profile'; @@ -78,6 +80,13 @@ public function get_sso_reconnect_dialog_url() { } public function process_authorization() { + if ( ! current_user_can( Ecwid_Admin::get_capability() ) ) { + wp_die( + esc_html__( 'You do not have sufficient permissions to connect the store.', 'ecwid-shopping-cart' ), + 403 + ); + } + $reconnect = isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'ec_oauth_reconnect'; if ( isset( $_REQUEST['error'] ) || ! isset( $_REQUEST['code'] ) ) { @@ -97,7 +106,11 @@ public function process_authorization() { ); } - wp_safe_redirect( Ecwid_Admin::get_dashboard_url() . '&connection_error' . ( $reconnect ? '&reconnect' : '' ) ); + if ( $reconnect ) { + wp_safe_redirect( Ecwid_Admin_Main_Page::get_forced_reconnect_url( '&connection_error' ) ); + } else { + wp_safe_redirect( Ecwid_Admin::get_dashboard_url() . '&connection_error' ); + } exit; } @@ -180,6 +193,15 @@ public function process_authorization() { } public function disconnect_store() { + if ( ! current_user_can( Ecwid_Admin::get_capability() ) ) { + wp_die( + esc_html__( 'You do not have sufficient permissions to disconnect the store.', 'ecwid-shopping-cart' ), + 403 + ); + } + + check_admin_referer( self::NONCE_DISCONNECT ); + update_option( 'ecwid_store_id', ecwid_get_demo_store_id() ); $this->api->save_token( '' ); @@ -187,6 +209,16 @@ public function disconnect_store() { exit; } + /** + * Builds a nonce-signed store disconnect url. + * + * Returns a raw (unescaped) url. Escape it with esc_url() when printing into markup. + */ + public static function get_disconnect_url() { + return admin_url( 'admin-post.php?action=ec_disconnect' ) + . '&_wpnonce=' . wp_create_nonce( self::NONCE_DISCONNECT ); + } + public function get_safe_scopes_array( $scopes ) { if ( ! isset( $scopes ) || empty( $scopes ) ) { return $this->_get_default_scopes_array(); @@ -280,7 +312,11 @@ protected function trigger_auth_error( $mode = 'default' ) { EcwidPlatform::report_error( $last_error ); } - wp_safe_redirect( Ecwid_Admin::get_dashboard_url() . '&connection_error' . ( $mode == self::MODE_RECONNECT ? '&reconnect' : '' ) ); + if ( $mode == self::MODE_RECONNECT ) { + wp_safe_redirect( Ecwid_Admin_Main_Page::get_forced_reconnect_url( '&connection_error' ) ); + } else { + wp_safe_redirect( Ecwid_Admin::get_dashboard_url() . '&connection_error' ); + } exit(); } diff --git a/includes/class-ecwid-product-popup.php b/includes/class-ecwid-product-popup.php index 43f0cf47..b5f409c9 100644 --- a/includes/class-ecwid-product-popup.php +++ b/includes/class-ecwid-product-popup.php @@ -175,6 +175,8 @@ public function add_scripts() { 'lastPage' => __( 'Last Page', 'ecwid-shopping-cart' ), ); + $data['reconnect_url'] = Ecwid_Admin_Main_Page::get_forced_reconnect_url( '&reason=spw' ); + wp_localize_script( 'ecwid-product-popup', 'ecwidSpwParams', $data ); } diff --git a/includes/importer/class-ecwid-import-page.php b/includes/importer/class-ecwid-import-page.php index adaa5c13..83d0e333 100644 --- a/includes/importer/class-ecwid-import-page.php +++ b/includes/importer/class-ecwid-import-page.php @@ -156,9 +156,10 @@ public function do_reconnect() { } wp_safe_redirect( - 'admin.php?page=' . Ecwid_Admin::ADMIN_SLUG - . '&reconnect&return-url=' . rawurlencode( $url ) - . '&scope=create_catalog+update_catalog&do_reconnect=1' + Ecwid_Admin_Main_Page::get_forced_reconnect_url( + '&return-url=' . rawurlencode( $url ) + . '&scope=create_catalog+update_catalog&do_reconnect=1' + ) ); } diff --git a/js/product-popup.js b/js/product-popup.js index 8d293a6c..2fbb1211 100644 --- a/js/product-popup.js +++ b/js/product-popup.js @@ -16,7 +16,7 @@ jQuery(document).ready(function () { openPopup = function () { if (ecwidSpwParams && typeof ecwidSpwParams.no_token != 'undefined') { - location.href = 'admin.php?page=ec-store&reconnect&reason=spw'; + location.href = ecwidSpwParams.reconnect_url; return false; } diff --git a/readme.txt b/readme.txt index d7064cd5..e0297010 100644 --- a/readme.txt +++ b/readme.txt @@ -4,8 +4,8 @@ Tags: ecommerce, e-commerce, storefront, shopping cart, online store License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Requires at least: 4.4 -Tested up to: 6.9 -Stable tag: 7.0.7 +Tested up to: 7.0 +Stable tag: 7.0.9 Powerful, easy to use ecommerce shopping cart for WordPress. Sell on Facebook and Instagram. iPhone & Android apps. Superb support. @@ -152,6 +152,13 @@ You can use Ecwid’s built-in import tools to copy your store products from any * [Ecwid Help Center](http://help.ecwid.com "Ecwid Help") == Changelog == += 7.0.9 - Aug 8, 2026 = +- **WordPress 7.0 compatibility.** The new WordPress version is released. The Ecwid ecommerce shopping cart plugin is ready for the new release — everything works well in your WordPress admin and storefront pages. Feel free to upgrade your site to WordPress 7.0. +- **Plugin code improvements for better security. Ecwid ecommerce shopping cart plugin update recommended.** Thanks to Alexander Jurkschat for responsibly reporting the issue. + += 7.0.8 - Feb 13, 2026 = +- **Plugin code improvements for better security. Ecwid ecommerce shopping cart plugin update recommended.** + = 7.0.7 - Jan 29, 2026 = - **Plugin code improvements for better security. Ecwid ecommerce shopping cart plugin update recommended.** diff --git a/templates/admin-footer.php b/templates/admin-footer.php index 6a1092e8..8bf59b5f 100644 --- a/templates/admin-footer.php +++ b/templates/admin-footer.php @@ -6,7 +6,7 @@ diff --git a/templates/admin/developers.php b/templates/admin/developers.php index c1d4ecd8..9d8248e8 100644 --- a/templates/admin/developers.php +++ b/templates/admin/developers.php @@ -368,32 +368,6 @@
-
-
-
-
- - - -
-
-
-
-
- -
-
- -
-
-
- -
-
-
-
-
-
@@ -486,30 +460,6 @@
-
-
-
-
- -
-
-
-
-
- -
-
- -
-
-
- -
-
-
-
-
-
diff --git a/templates/admin/simple-dashboard.php b/templates/admin/simple-dashboard.php index 9d49497d..ef36c96f 100644 --- a/templates/admin/simple-dashboard.php +++ b/templates/admin/simple-dashboard.php @@ -15,7 +15,7 @@
  • - +