PluginProbe
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services / 8.7.6
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services v8.7.6
8.7.6 8.7.5 8.7.4 8.7.3 8.7.2 8.7.1 8.7.0 8.6.9 8.6.8 8.6.7 8.6.6 8.6.5 8.6.4 8.6.2 8.6.1 8.6.0 8.5.9 8.5.8 8.5.7 8.5.6 8.5.5 8.5.4 8.5.3 8.5.2 8.5.0 All 532 releases
← All changes | functions.php +191 -6 8.6.68.7.6 View file →
@@ -58,8 +58,62 @@
58 58 });
59 59 </script>
60 60 <?php
61 61 }
62 +/**
63 + * Extract a YouTube video ID from common URL formats.
64 + *
65 + * @param string $url YouTube watch, embed, short, or youtu.be URL.
66 + * @return string Video ID or empty string.
67 + */
68 +if ( ! function_exists( 'qcld_wpbot_extract_youtube_id' ) ) {
69 + function qcld_wpbot_extract_youtube_id( $url ) {
70 + $url = trim( (string) $url );
71 + if ( $url === '' ) {
72 + return '';
73 + }
74 +
75 + if ( preg_match( '/(?:youtube\.com\/(?:embed\/|shorts\/|live\/|watch\?(?:.*&)?v=)|youtu\.be\/)([A-Za-z0-9_-]{11})/', $url, $matches ) ) {
76 + return $matches[1];
77 + }
78 +
79 + $path = (string) wp_parse_url( $url, PHP_URL_PATH );
80 + $base = basename( $path );
81 + if ( preg_match( '/^[A-Za-z0-9_-]{11}$/', $base ) ) {
82 + return $base;
83 + }
84 +
85 + return '';
86 + }
87 +}
88 +if ( ! function_exists( 'qcld_wpbot_youtube_icon_embed_src' ) ) {
89 + function qcld_wpbot_youtube_icon_embed_src( $url ) {
90 + $video_id = qcld_wpbot_extract_youtube_id( $url );
91 + if ( $video_id === '' ) {
92 + return '';
93 + }
94 +
95 + return add_query_arg(
96 + array(
97 + 'autoplay' => '1',
98 + 'mute' => '1',
99 + 'loop' => '1',
100 + 'playlist' => $video_id,
101 + 'controls' => '0',
102 + 'showinfo' => '0',
103 + 'rel' => '0',
104 + 'fs' => '0',
105 + 'iv_load_policy' => '3',
106 + 'cc_load_policy' => '0',
107 + 'disablekb' => '1',
108 + 'playsinline' => '1',
109 + 'modestbranding' => '1',
110 + 'color' => 'white',
111 + ),
112 + 'https://www.youtube.com/embed/' . rawurlencode( $video_id )
113 + );
114 + }
115 +}
62 116 function wp_chatbot_load_footer_html(){
63 117 if ( get_option('disable_wp_chatbot') != 1 && wp_chatbot_load_controlling() === true) {
64 118
65 119 ?>
@@ -79,10 +133,27 @@
79 133 }
80 134 ?>
81 135 <style>
82 136 .wp-chatbot-container {
137 + background-color: #eceef3 !important;
83 138 background-image: url(<?php echo esc_url($qcld_wb_chatbot_board_bg_path); ?>) !important;
139 + background-size: cover !important;
140 + background-position: center !important;
141 + background-repeat: no-repeat !important;
84 142 }
143 + .wp-chatbot-template-01 #wp-chatbot-board-container,
144 + .wp-chatbot-template-01 .wp-chatbot-board-container {
145 + background-color: #eceef3 !important;
146 + background-image: none !important;
147 + }
148 + .wp-chatbot-template-01 #wp-chatbot-board-container::before,
149 + .wp-chatbot-template-01 .wp-chatbot-board-container::before {
150 + background-color: #eceef3 !important;
151 + background-image: url(<?php echo esc_url($qcld_wb_chatbot_board_bg_path); ?>) !important;
152 + background-size: cover !important;
153 + background-position: center !important;
154 + background-repeat: no-repeat !important;
155 + }
85 156 </style>
86 157 <?php }
87 158 $wp_chatbot_enable_rtl = "";
88 159 if (get_option('enable_wp_chatbot_rtl') == '1') {
@@ -180,14 +251,72 @@
180 251 $wp_chatbot_custom_icon_path = QCLD_wpCHATBOT_IMG_URL . get_option('wp_chatbot_icon');
181 252 } else {
182 253 $wp_chatbot_custom_icon_path = QCLD_wpCHATBOT_IMG_URL . 'custom.png';
183 254 }
255 + $_wpbot_icon_video = get_option('wp_chatbot_icon_video', '');
256 + $_wpbot_video_is_youtube = ( strpos( $_wpbot_icon_video, 'youtube.com' ) !== false || strpos( $_wpbot_icon_video, 'youtu.be' ) !== false );
257 + $_wpbot_youtube_embed_src = $_wpbot_video_is_youtube ? qcld_wpbot_youtube_icon_embed_src( $_wpbot_icon_video ) : '';
258 + $_wpbot_video_delay_ms = absint( get_option( 'wp_chatbot_icon_video_delay', 0 ) ) * 1000;
259 +
260 + $wp_chatbot_ball_is_youtube = ($_wpbot_icon_video !== '' && (strpos($_wpbot_icon_video, 'youtube.com') !== false || strpos($_wpbot_icon_video, 'youtu.be') !== false));
261 + $wp_chatbot_ball_is_video = ($_wpbot_icon_video !== '' && !$wp_chatbot_ball_is_youtube);
262 + $wp_chatbot_ball_has_video = ($wp_chatbot_ball_is_youtube || $wp_chatbot_ball_is_video);
184 263 ?>
185 264 <img src="<?php echo esc_url($wp_chatbot_custom_icon_path); ?>"
186 - alt="wpChatIcon" qcld_agent="<?php echo esc_url($wp_chatbot_custom_icon_path); ?>" >
187 -
265 + alt="wpChatIcon" qcld_agent="<?php echo esc_url($wp_chatbot_custom_icon_path); ?>"
266 + id="wp-chatbot-ball-icon-img"
267 + <?php if ($wp_chatbot_ball_has_video) { echo 'style="display:none;"'; } ?> >
268 + <?php if ( $_wpbot_icon_video !== '' ) : ?>
269 + <?php if ( $_wpbot_video_is_youtube && $_wpbot_youtube_embed_src !== '' ) : ?>
270 + <iframe class="wpbot-icon-video" src="<?php echo $_wpbot_video_delay_ms > 0 ? 'about:blank' : esc_url( $_wpbot_youtube_embed_src ); ?>" data-wpbot-yt-src="<?php echo esc_url( $_wpbot_youtube_embed_src ); ?>" frameborder="0" allow="autoplay; fullscreen; encrypted-media; picture-in-picture"></iframe>
271 + <?php elseif ( ! $_wpbot_video_is_youtube ) : ?>
272 + <video class="wpbot-icon-video" src="<?php echo esc_url( $_wpbot_icon_video ); ?>" autoplay muted loop playsinline preload="auto"></video>
273 + <?php endif; ?>
274 + <?php endif; ?>
188 275 </div>
276 +
189 277 </div>
278 + <?php
279 + if ( $_wpbot_icon_video !== '' ) :
280 + ?>
281 + <script>
282 + (function(){
283 + var wpbotDelay = <?php echo (int) $_wpbot_video_delay_ms; ?>;
284 + function wpbotForcePlay(){
285 + var v = document.querySelector('#wp-chatbot-ball video.wpbot-icon-video');
286 + if( v ){
287 + v.muted = true;
288 + v.volume = 0;
289 + v.loop = true;
290 + var tries = 0, maxTries = 30;
291 + var timer = setInterval(function(){
292 + tries++;
293 + v.play().then(function(){ clearInterval(timer); }).catch(function(){});
294 + if( tries >= maxTries ) clearInterval(timer);
295 + }, 300);
296 + }
297 + var yt = document.querySelector('#wp-chatbot-ball iframe.wpbot-icon-video');
298 + if( yt ){
299 + var ytSrc = yt.getAttribute('data-wpbot-yt-src');
300 + if( ytSrc && ( !yt.getAttribute('src') || yt.getAttribute('src') === 'about:blank' || yt.getAttribute('src').indexOf('autoplay=1') === -1 ) ){
301 + yt.setAttribute('src', ytSrc);
302 + }
303 + }
304 + }
305 + function wpbotDelayedPlay(){
306 + setTimeout(wpbotForcePlay, wpbotDelay);
307 + }
308 + if( document.readyState === 'loading' ){
309 + document.addEventListener('DOMContentLoaded', wpbotDelayedPlay);
310 + } else {
311 + wpbotDelayedPlay();
312 + }
313 + window.addEventListener('load', function(){
314 + setTimeout(wpbotForcePlay, wpbotDelay);
315 + });
316 + })();
317 + </script>
318 + <?php endif; ?>
190 319 <?php
191 320 $fb_app_id = get_option('qlcd_wp_chatbot_fb_app_id');
192 321 $fb_page_id = get_option('qlcd_wp_chatbot_fb_page_id');
193 322 $fb_mgs_color = get_option('qlcd_wp_chatbot_fb_color') != '' ? get_option('qlcd_wp_chatbot_fb_color') : '#0084ff';
@@ -1806,15 +1935,68 @@
1806 1935 }
1807 1936
1808 1937 }
1809 1938
1939 +/**
1940 + * Safely sanitize chatbot conversation input.
1941 + *
1942 + * SECURITY FIX (CVE WPBot Stored XSS ≤ 8.6.9):
1943 + * The previous order was: wp_kses() → html_entity_decode() → htmlspecialchars().
1944 + * An attacker could submit entity-encoded payloads (&lt;img onerror=...&gt;) that
1945 + * bypassed wp_kses (which saw inert text), were then decoded back into live markup
1946 + * by html_entity_decode(), and survived into storage and the admin UI.
1947 + *
1948 + * Correct order: html_entity_decode() FIRST → wp_kses() → htmlspecialchars().
1949 + * wp_kses() now sees the real decoded markup and strips forbidden tags/attributes.
1950 + *
1951 + * @param string $data Raw conversation string (already wp_unslash'd by caller).
1952 + * @return string Sanitized, entity-encoded string safe for DB storage.
1953 + */
1810 1954 function qcld_wpbot_input_validation( $data ) {
1811 - $data = html_entity_decode($data);
1812 - $data = trim($data);
1813 - $data = stripslashes($data);
1814 - $data = htmlspecialchars($data);
1955 + // 1. Decode any entity-encoded HTML so wp_kses sees the real markup.
1956 + $data = html_entity_decode( $data, ENT_QUOTES | ENT_HTML5, 'UTF-8' );
1957 + $data = trim( $data );
1958 + $data = stripslashes( $data );
1959 + // 2. Sanitize with a strict allowlist — NOW operating on decoded markup.
1960 + $data = wp_kses( $data, wpbot_get_safe_conversation_tags() );
1961 + // 3. Re-encode for safe DB storage; admin.js decodes for rendering.
1962 + $data = htmlspecialchars( $data, ENT_QUOTES | ENT_HTML5, 'UTF-8' );
1815 1963 return $data;
1816 1964 }
1965 +
1966 +/**
1967 + * Returns the strict HTML allowlist for chatbot conversation content.
1968 + *
1969 + * Critically: no event-handler attributes (onerror, onclick, onload, etc.) are
1970 + * allowed — wp_kses strips any attribute not explicitly listed here.
1971 + * 'img' is intentionally omitted; bot responses that include images should use
1972 + * safe URLs only and can be re-added with only 'src', 'alt', 'class' if needed.
1973 + *
1974 + * @return array<string, array<string, bool>>
1975 + */
1976 +function wpbot_get_safe_conversation_tags() {
1977 + return array(
1978 + 'ul' => array( 'class' => true ),
1979 + 'ol' => array( 'class' => true ),
1980 + 'li' => array( 'class' => true, 'id' => true ),
1981 + 'div' => array( 'class' => true, 'id' => true ),
1982 + 'span' => array( 'class' => true, 'id' => true ),
1983 + 'p' => array( 'class' => true ),
1984 + 'br' => array(),
1985 + 'strong' => array(),
1986 + 'em' => array(),
1987 + 'b' => array(),
1988 + 'i' => array(),
1989 + 'a' => array(
1990 + 'href' => true,
1991 + 'target' => true,
1992 + 'rel' => true,
1993 + 'class' => true,
1994 + ),
1995 + // 'img' intentionally excluded — prevents onerror/onload injection.
1996 + // Add back with only 'src','alt','class' if bot image responses are needed.
1997 + );
1998 +}
1817 1999 add_action('wp_ajax_qcld_small_talk_import', 'qcld_small_talk_import');
1818 2000 function qcld_small_talk_import(){
1819 2001 if ( ! current_user_can( 'manage_options' ) ) {
1820 2002 wp_die();
@@ -1892,4 +2074,7 @@
1892 2074
1893 2075 }
1894 2076 }
1895 2077 }
2078 +
2079 +// AI Actions Chat Preview
2080 +