PluginProbe
Ultimate Store Kit – Store Builder Addons for Elementor, WooCommerce Store Builder, EDD Store Builder / 3.1.4
Ultimate Store Kit – Store Builder Addons for Elementor, WooCommerce Store Builder, EDD Store Builder v3.1.4
3.1.4 3.0.8 3.0.9 3.1.0 3.1.2 3.1.3 3.0.7 3.0.5 3.0.4 3.0.3 3.0.2 trunk 1.5.0 1.5.1 1.5.2 1.6.1 1.6.2 1.6.3 1.6.4 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 All 93 releases
← All changes | includes/builder/builder-integration.php +26 -58 3.1.03.1.4 View file →
@@ -5,9 +5,9 @@
5 5 if (! defined('ABSPATH')) {
6 6 exit; // Exit if accessed directly
7 7 }
8 8
9 -// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals -- usk_ / BDTUSK_ / ultimate-store-kit- are this plugin's established public prefixes. Ultimate Store Kit Pro calls into these names, as does third-party integration code, so renaming them is a breaking change. Plugin Check only recognises prefixes derived verbatim from the slug and so reports them as unprefixed.
9 +// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals -- BDTUSK_ / ultimate_store_kit_ / ultimate-store-kit- are this plugin's established public prefixes.
10 10
11 11 if (! defined('WPINC')) {
12 12 die;
13 13 }
@@ -35,39 +35,16 @@
35 35 add_filter("elementor/document/urls/wp_preview", [$this, 'change_preview_editor_url'], 999, 2);
36 36
37 37 add_action('elementor/documents/register_controls', [$this, 'register_document_controls']);
38 38
39 - // Add demo bypass filter for template preview
40 - add_filter('ultimate_store_kit/preview/verified_bypass', function ($verify) {
41 - // Check if we're in a demo environment or development site
42 - // For demo sites, you might want to check domain names or other indicators
43 - $demo_hosts = apply_filters('ultimate_store_kit/demo_hosts', [
44 - 'storekit.pro',
45 - 'demo.storekit.pro',
46 - 'localhost',
47 - '127.0.0.1'
48 - ]);
49 -
50 - $current_host = isset($_SERVER['HTTP_HOST']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])) : '';
51 -
52 - foreach ($demo_hosts as $host) {
53 - if (strpos($current_host, $host) !== false) {
54 - return true;
55 - }
56 - }
57 -
58 - return $verify;
59 - });
60 -
61 - // Add filter to enable demo mode for preview URLs
62 - add_filter('ultimate_store_kit/preview/use_demo_bypass', function ($use_demo) {
63 - // Enable demo bypass in Elementor editor
64 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only check on whether the Elementor editor is loading.
65 - if (isset($_GET['action']) && $_GET['action'] === 'elementor') {
66 - return true;
67 - }
68 - return $use_demo;
69 - });
39 + // The template preview used to accept the literal string "verified" in place
40 + // of a nonce whenever $_SERVER['HTTP_HOST'] contained one of a list of demo
41 + // hostnames. Because Host is attacker-controlled and the check was a substring
42 + // match, any unauthenticated visitor could render the Elementor content of an
43 + // arbitrary post id -- including drafts and private posts -- on any site whose
44 + // Host reached PHP as localhost/127.0.0.1 (common behind a reverse proxy) or
45 + // whose domain merely contained one of those strings. Preview is now gated on
46 + // the real per-post nonce plus an edit_post capability check; see get_template_id().
70 47 }
71 48
72 49 public function change_preview_editor_url($url, $document) {
73 50 $post_id = $document->get_main_id();
@@ -144,15 +121,12 @@
144 121 if (empty($template_url)) {
145 122 return $url;
146 123 }
147 124
148 - $is_demo = apply_filters('ultimate_store_kit/preview/use_demo_bypass', false);
149 - $nonce_value = $is_demo ? 'verified' : wp_create_nonce('template_preview_' . $post_id);
150 -
151 125 $param = [
152 - 'usk_template_id' => $post_id,
153 - 'preview_nonce' => $nonce_value,
154 - 'preview' => true
126 + 'ultimate_store_kit_template_id' => $post_id,
127 + 'ultimate_store_kit_preview_nonce' => wp_create_nonce('ultimate_store_kit_template_preview_' . $post_id),
128 + 'preview' => true
155 129 ];
156 130
157 131 // Add parameters two URL
158 132 $url = add_query_arg($param, $template_url);
@@ -201,9 +175,9 @@
201 175 return;
202 176 }
203 177 $meta = get_post_meta($post->ID);
204 178
205 - $templateMeta = usk_optional($meta)[Meta::TEMPLATE_TYPE];
179 + $templateMeta = ultimate_store_kit_optional($meta)[Meta::TEMPLATE_TYPE];
206 180 if (! isset($templateMeta[0])) {
207 181 return;
208 182 }
209 183 $postMeta = $templateMeta[0];
@@ -404,9 +378,9 @@
404 378 return $this->getTemplatePath('home', $template);
405 379 }
406 380 }
407 381
408 - if ($page_Id = intval(get_option('bdt_usk_compare_products_page_id'))) {
382 + if ($page_Id = ultimate_store_kit_get_compare_page_option()) {
409 383 if (is_page($page_Id)) {
410 384 if ($custom_template = $this->get_template_id('compare-products', 'product')) {
411 385 $this->current_template_id = $custom_template;
412 386 return $this->getTemplatePath('home', $template);
@@ -448,32 +422,26 @@
448 422 if (null !== $this->current_template_id) {
449 423 return $this->current_template_id;
450 424 }
451 425
452 - // Handle template preview from URL parameters
453 - if (!empty($_GET['preview']) && !empty($_GET['usk_template_id']) && !empty($_GET['preview_nonce'])) {
454 - $usk_template_id = sanitize_text_field(wp_unslash($_GET['usk_template_id']));
455 - $nonce = sanitize_text_field(wp_unslash($_GET['preview_nonce']));
426 + // Handle template preview from URL parameters.
427 + if (!empty($_GET['preview']) && !empty($_GET['ultimate_store_kit_template_id']) && !empty($_GET['ultimate_store_kit_preview_nonce'])) {
428 + $usk_template_id = absint(wp_unslash($_GET['ultimate_store_kit_template_id']));
429 + $nonce = sanitize_text_field(wp_unslash($_GET['ultimate_store_kit_preview_nonce']));
456 430
457 - // Special handling for demo bypass
458 - $is_demo_bypass = ($nonce === 'verified');
459 - $nonce_verified = $is_demo_bypass ?
460 - apply_filters('ultimate_store_kit/preview/verified_bypass', false) :
461 - wp_verify_nonce($nonce, 'template_preview_' . $usk_template_id);
431 + // The nonce is bound to the specific template and to the user who
432 + // generated it, and the capability check makes sure a leaked preview
433 + // URL cannot be replayed by someone who may not edit the template.
434 + $nonce_verified = $usk_template_id
435 + && wp_verify_nonce($nonce, 'ultimate_store_kit_template_preview_' . $usk_template_id)
436 + && current_user_can('edit_post', $usk_template_id);
462 437
463 - if ($nonce_verified) {
464 - // For demo bypass mode, we don't need to check template type
465 - if ($is_demo_bypass) {
466 - $this->current_template_id = (int)$usk_template_id;
467 - return $this->current_template_id;
468 - }
469 -
470 - // For normal preview, check template type
438 + if ($nonce_verified && get_post_type($usk_template_id) === Meta::POST_TYPE) {
471 439 $template_type = get_post_meta($usk_template_id, Meta::TEMPLATE_TYPE, true);
472 440 if (!empty($template_type)) {
473 441 $template_data = explode(Builder_Template_Helper::separator(), $template_type);
474 442 if (count($template_data) >= 2 && $template_data[1] === $slug && ($postType === false || $template_data[0] === $postType)) {
475 - $this->current_template_id = (int)$usk_template_id;
443 + $this->current_template_id = $usk_template_id;
476 444 return $this->current_template_id;
477 445 }
478 446 }
479 447 }