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 +32 -56 3.0.73.1.4 View file →
@@ -1,8 +1,14 @@
1 1 <?php
2 2
3 3 namespace UltimateStoreKit\Builder;
4 4
5 +if (! defined('ABSPATH')) {
6 + exit; // Exit if accessed directly
7 +}
8 +
9 +// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals -- BDTUSK_ / ultimate_store_kit_ / ultimate-store-kit- are this plugin's established public prefixes.
10 +
5 11 if (! defined('WPINC')) {
6 12 die;
7 13 }
8 14
@@ -29,38 +35,16 @@
29 35 add_filter("elementor/document/urls/wp_preview", [$this, 'change_preview_editor_url'], 999, 2);
30 36
31 37 add_action('elementor/documents/register_controls', [$this, 'register_document_controls']);
32 38
33 - // Add demo bypass filter for template preview
34 - add_filter('ultimate_store_kit/preview/verified_bypass', function ($verify) {
35 - // Check if we're in a demo environment or development site
36 - // For demo sites, you might want to check domain names or other indicators
37 - $demo_hosts = apply_filters('ultimate_store_kit/demo_hosts', [
38 - 'storekit.pro',
39 - 'demo.storekit.pro',
40 - 'localhost',
41 - '127.0.0.1'
42 - ]);
43 -
44 - $current_host = isset($_SERVER['HTTP_HOST']) ? sanitize_text_field($_SERVER['HTTP_HOST']) : '';
45 -
46 - foreach ($demo_hosts as $host) {
47 - if (strpos($current_host, $host) !== false) {
48 - return true;
49 - }
50 - }
51 -
52 - return $verify;
53 - });
54 -
55 - // Add filter to enable demo mode for preview URLs
56 - add_filter('ultimate_store_kit/preview/use_demo_bypass', function ($use_demo) {
57 - // Enable demo bypass in Elementor editor
58 - if (isset($_GET['action']) && $_GET['action'] === 'elementor') {
59 - return true;
60 - }
61 - return $use_demo;
62 - });
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().
63 47 }
64 48
65 49 public function change_preview_editor_url($url, $document) {
66 50 $post_id = $document->get_main_id();
@@ -137,15 +121,12 @@
137 121 if (empty($template_url)) {
138 122 return $url;
139 123 }
140 124
141 - $is_demo = apply_filters('ultimate_store_kit/preview/use_demo_bypass', false);
142 - $nonce_value = $is_demo ? 'verified' : wp_create_nonce('template_preview_' . $post_id);
143 -
144 125 $param = [
145 - 'usk_template_id' => $post_id,
146 - 'preview_nonce' => $nonce_value,
147 - '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
148 129 ];
149 130
150 131 // Add parameters two URL
151 132 $url = add_query_arg($param, $template_url);
@@ -154,8 +135,9 @@
154 135 }
155 136
156 137 public function my_custom_fonts() {
157 138 if (is_admin() && Plugin::instance()->editor->is_edit_mode()) {
139 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only check on whether a builder template is open; only enqueues a style.
158 140 if (isset($_REQUEST['usk-template'])) {
159 141 wp_register_style('usk-template-builder-hide-preview-btn-inline', false); // phpcs:ignore
160 142 wp_enqueue_style('usk-template-builder-hide-preview-btn-inline');
161 143 wp_add_inline_style(
@@ -193,9 +175,9 @@
193 175 return;
194 176 }
195 177 $meta = get_post_meta($post->ID);
196 178
197 - $templateMeta = optional($meta)[Meta::TEMPLATE_TYPE];
179 + $templateMeta = ultimate_store_kit_optional($meta)[Meta::TEMPLATE_TYPE];
198 180 if (! isset($templateMeta[0])) {
199 181 return;
200 182 }
201 183 $postMeta = $templateMeta[0];
@@ -396,9 +378,9 @@
396 378 return $this->getTemplatePath('home', $template);
397 379 }
398 380 }
399 381
400 - if ($page_Id = intval(get_option('bdt_usk_compare_products_page_id'))) {
382 + if ($page_Id = ultimate_store_kit_get_compare_page_option()) {
401 383 if (is_page($page_Id)) {
402 384 if ($custom_template = $this->get_template_id('compare-products', 'product')) {
403 385 $this->current_template_id = $custom_template;
404 386 return $this->getTemplatePath('home', $template);
@@ -440,32 +422,26 @@
440 422 if (null !== $this->current_template_id) {
441 423 return $this->current_template_id;
442 424 }
443 425
444 - // Handle template preview from URL parameters
445 - if (!empty($_GET['preview']) && !empty($_GET['usk_template_id']) && !empty($_GET['preview_nonce'])) {
446 - $usk_template_id = sanitize_text_field(wp_unslash($_GET['usk_template_id']));
447 - $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']));
448 430
449 - // Special handling for demo bypass
450 - $is_demo_bypass = ($nonce === 'verified');
451 - $nonce_verified = $is_demo_bypass ?
452 - apply_filters('ultimate_store_kit/preview/verified_bypass', false) :
453 - 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);
454 437
455 - if ($nonce_verified) {
456 - // For demo bypass mode, we don't need to check template type
457 - if ($is_demo_bypass) {
458 - $this->current_template_id = (int)$usk_template_id;
459 - return $this->current_template_id;
460 - }
461 -
462 - // For normal preview, check template type
438 + if ($nonce_verified && get_post_type($usk_template_id) === Meta::POST_TYPE) {
463 439 $template_type = get_post_meta($usk_template_id, Meta::TEMPLATE_TYPE, true);
464 440 if (!empty($template_type)) {
465 441 $template_data = explode(Builder_Template_Helper::separator(), $template_type);
466 442 if (count($template_data) >= 2 && $template_data[1] === $slug && ($postType === false || $template_data[0] === $postType)) {
467 - $this->current_template_id = (int)$usk_template_id;
443 + $this->current_template_id = $usk_template_id;
468 444 return $this->current_template_id;
469 445 }
470 446 }
471 447 }