[17:12:34] === CVE-2026-8441 variant search and fixed-control validation === [17:12:34] Bundle root: /data/pruva/runs/52897a84-76e4-425d-abf6-ea2f2eb78fb0/bundle [17:12:34] === Phase 1: Install/check runtime dependencies === [17:12:34] PHP: PHP 8.5.4 (cli) (built: May 25 2026 12:19:37) (NTS) [17:12:34] MariaDB: mariadbd Ver 11.8.6-MariaDB-5 from Ubuntu for debian-linux-gnu on x86_64 (-- Please help get to 10k stars at https://github.com/MariaDB/Server) [17:12:34] === Phase 2: Verify genuine WP Review Slider Pro 12.6.7 source and reviewed candidates === sha256 7f6092f4ea58b5c5c0dba72ba014b9395bf9608f9aeeb95206e80dc14f0b17e5 /data/pruva/runs/52897a84-76e4-425d-abf6-ea2f2eb78fb0/bundle/repro/vendor/wp-review-slider-pro_v12.6.7.zip --- Plugin header from bundled real product zip --- * @wordpress-plugin * Plugin Name: WP Review Slider Pro (Premium) * Plugin URI: https://wpreviewslider.com/ * Description: Pro Version - Allows you to easily display your Facebook Page, Yelp, Google, Manually Input, and 80+ other site reviews in your Posts, Pages, and Widget areas. * Version: 12.6.7 * Update URI: https://api.freemius.com * Author: LJ Apps * Author URI: http://ljapps.com/ --- Original notinstring vulnerable construction --- 32 //add a not in statement after $sortdir if we are rand search ex: AND book_price NOT IN (100,200) 33 if($notinstring!=''){ 34 //explode implode for safety 35 $tempnotinarray = explode(",",$notinstring); 36 if(is_array($tempnotinarray)){ 37 $notinstring = implode(",",$tempnotinarray); 38 $notinsearchstring = " AND id NOT IN (".$notinstring.") "; 39 } --- Alternate public filter candidates in GetReviews_Functions::wppro_queryreviews() --- 57 //add text search if we are using pagination and the search box 58 $textsearchquery = ''; 59 $tagsearch=''; 60 if(!isset($template_misc_array['header_tag_search'])){ 61 $template_misc_array['header_tag_search']=''; 62 } 63 if($textsearch!=''){ 64 if($template_misc_array['header_tag_search']=='tags'){ 65 $textsearchquery = "AND (tags LIKE '%%".sanitize_text_field($textsearch)."%%')"; 66 } else if($template_misc_array['header_tag_search']=='both'){ 67 $textsearchquery = "AND (reviewer_name LIKE '%%".sanitize_text_field($textsearch)."%%' or review_text LIKE '%%".sanitize_text_field($textsearch)."%%' or review_title LIKE '%%".sanitize_text_field($textsearch)."%%' or tags LIKE '%%".sanitize_text_field($textsearch)."%%' or type LIKE '%%".sanitize_text_field($textsearch)."%%' or meta_data LIKE '%%".sanitize_text_field($textsearch)."%%')"; 68 } else { 69 $textsearchquery = "AND (reviewer_name LIKE '%%".sanitize_text_field($textsearch)."%%' or review_text LIKE '%%".sanitize_text_field($textsearch)."%%' or review_title LIKE '%%".sanitize_text_field($textsearch)."%%' or type LIKE '%%".sanitize_text_field($textsearch)."%%')"; 70 } 490 } 491 //language code filter on front end 492 $publiclangfilter=''; 493 if($textlang!='' && $textlang!='unset'){ 494 $publiclangfilter = " AND language_code = '".sanitize_text_field($textlang)."'"; 495 } 496 //source code filter on front end 497 $publicsourcefilter=''; 498 if($textsource!='' && $textsource!='unset'){ 499 $publicsourcefilter = " AND pageid = '".sanitize_text_field($textsource)."'"; 500 } 501 --- Query concatenation that appends filters --- 690 //find total and average in db 691 $nolimitreviews = $wpdb->get_results($querynolimit,ARRAY_A); 692 } 693 } else { 694 $totalreviews = $wpdb->get_results( 695 $wpdb->prepare("SELECT * FROM ".$table_name." 696 ".$hidenquery." ".$lengthquery." ".$rtypefilter." ".$rpagefilter." ".$rpostidfilter." ".$rstringfilter." ".$rstringfilternot." ".$rcatidfilter." ".$tagfilter." ".$mediafilter." ".$langfilter." ".$shortlangfilter." ".$shortcodetagfilter." ".$randlimitfilter."".$ratingquery."".$notinsearchstring."".$textsearchquery."".$ratingquerypublic."".$publiclangfilter."".$publicsourcefilter."".$publicrtypefilter." 697 ORDER BY ".$sorttable." ".$sortdir." LIMIT ".$tablelimit." ",$hidenqueryvar) 698 ); 699 $totalreviewsarray['dbcall'] = $wpdb->last_query; 700 //run another query if we need total and average. 701 if(!$skip_aggregate_queries && ($currentform[0]->google_snippet_add=='yes' || $currentform[0]->load_more=='yes' || $template_misc_array['header_text']!='' || $template_misc_array['header_rtypes']=='yes' || $template_misc_array['header_banner']!='')){ 702 $notinsearchstring =''; 703 $nolimitreviews = $wpdb->get_results( 704 $wpdb->prepare("SELECT * FROM ".$table_name." 705 ".$hidenquery." ".$lengthquery." ".$rtypefilter." ".$rpagefilter." ".$rpostidfilter." ".$rstringfilter." ".$rstringfilternot." ".$rcatidfilter." ".$tagfilter." ".$mediafilter." ".$langfilter." ".$shortlangfilter." ".$shortcodetagfilter." ".$randlimitfilter."".$ratingquery."".$notinsearchstring."".$textsearchquery."".$ratingquerypublic."".$publiclangfilter."".$publicsourcefilter."".$publicrtypefilter." 706 ORDER BY ".$sorttable." ".$sortdir." ",$hidenqueryvar),ARRAY_A); --- Public unauthenticated AJAX action registration --- 1556 1557 //add ajax for getting the load more reviews, called when someone clicks the load more button 1558 $this->loader->add_action( 'wp_ajax_wprp_load_more_revs', $plugin_public, 'wppro_loadmore_revs_ajax' ); 1559 $this->loader->add_action( 'wp_ajax_nopriv_wprp_load_more_revs', $plugin_public, 'wppro_loadmore_revs_ajax' ); 1560 [17:12:34] === Phase 3: Start MariaDB === [17:12:40] MariaDB ready on 127.0.0.1:52167 (PID 223374) [17:12:40] === Phase 4: Install WordPress and genuine plugin === name,status,version akismet,inactive,5.3.5 hello,inactive,1.7.2 wp-review-slider-pro,active,12.6.7 [17:12:45] === Phase 5: Seed public reviews and a load-more template === seeded_template_id=1 seeded_page_id=4 review_count=3 [17:12:45] === Phase 6: Start WordPress HTTP service and extract public nonce === [17:12:47] WordPress service healthy on http://127.0.0.1:55507/wp-admin/admin-ajax.php; extracted public nonce c3ac783368 [17:12:47] === Phase 7: Baseline original notinstring vulnerability on vulnerable source === [17:12:50] Vulnerable original notinstring SLEEP(3): 3.109833s [17:12:50] === Phase 8: Apply original notinstring-only fixed patch === --- /data/pruva/runs/52897a84-76e4-425d-abf6-ea2f2eb78fb0/bundle/vuln_variant/artifacts/getreviews_class.before_notin_patch.php 2026-07-05 17:12:50.385396602 +0000 +++ /data/pruva/runs/52897a84-76e4-425d-abf6-ea2f2eb78fb0/bundle/vuln_variant/artifacts/getreviews_class.after_notin_patch.php 2026-07-05 17:12:50.397396124 +0000 @@ -32,7 +32,8 @@ //add a not in statement after $sortdir if we are rand search ex: AND book_price NOT IN (100,200) if($notinstring!=''){ //explode implode for safety - $tempnotinarray = explode(",",$notinstring); + // CVE-2026-8441 notinstring fix control: only integer review IDs may enter the numeric NOT IN clause. + $tempnotinarray = array_filter(array_map('absint', explode(",", $notinstring))); if(is_array($tempnotinarray)){ $notinstring = implode(",",$tempnotinarray); $notinsearchstring = " AND id NOT IN (".$notinstring.") "; No syntax errors detected in /data/pruva/runs/52897a84-76e4-425d-abf6-ea2f2eb78fb0/bundle/vuln_variant/runtime/wordpress/wp-content/plugins/wp-review-slider-pro/public/partials/getreviews_class.php [17:12:51] === Phase 9: Verify fixed control blocks original notinstring payload === [17:12:51] Fixed-control original notinstring SLEEP(3): 0.044909s [17:12:51] === Phase 10: Test materially distinct public-field candidates on fixed control === [17:12:51] Fixed-control candidate textsource: 0.015890s [17:12:51] Fixed-control candidate textsearch: 0.015887s [17:12:52] Fixed-control candidate textlang: 0.015000s [17:12:52] Fixed-control candidate textrtype: 0.016840s [17:12:52] Fixed-control candidate shortcodepageid: 0.014518s { "vuln_original_notinstring_sleep": 3.109833, "fixed_original_notinstring_sleep": 0.044909, "fixed_textsource_sleep": 0.01589, "fixed_textsearch_sleep": 0.015887, "fixed_textlang_sleep": 0.015, "fixed_textrtype_sleep": 0.01684, "fixed_shortcodepageid_sleep": 0.014518, "thresholds": { "delay_min_seconds": 2.5, "fast_max_seconds": 1.5 }, "original_reproduced_before_patch": true, "original_blocked_after_patch": true, "bypass_confirmed": false, "confirmed": false } [ { "candidate": "textsource", "field": "textsource", "runtime_seconds_after_notin_patch": 0.01589, "result": "blocked_no_delay" }, { "candidate": "textsearch", "field": "textsearch", "runtime_seconds_after_notin_patch": 0.015887, "result": "blocked_no_delay" }, { "candidate": "textlang", "field": "textlang", "runtime_seconds_after_notin_patch": 0.015, "result": "blocked_no_delay" }, { "candidate": "textrtype", "field": "textrtype", "runtime_seconds_after_notin_patch": 0.01684, "result": "blocked_no_delay" }, { "candidate": "shortcodepageid", "field": "shortcodepageid", "runtime_seconds_after_notin_patch": 0.014518, "result": "blocked_no_delay" } ] CVE-2026-8441 variant search evidence Product source: bundled wp-review-slider-pro_v12.6.7.zip Product SHA256: 7f6092f4ea58b5c5c0dba72ba014b9395bf9608f9aeeb95206e80dc14f0b17e5 Endpoint: POST http://127.0.0.1:55507/wp-admin/admin-ajax.php Action: wprp_load_more_revs Nonce source: public page http://127.0.0.1:55507/?p=4 rendering [wprevpro_usetemplate tid="1"] Fixed control: same 12.6.7 source with only the original notinstring fix applied. Original vulnerable/fixed-control check: vulnerable notinstring SLEEP(3): 3.109833s fixed-control notinstring SLEEP(3): 0.044909s Distinct candidates tested after notinstring patch: textsource SLEEP(3) payload: 0.015890s textsearch SLEEP(3) payload: 0.015887s textlang SLEEP(3) payload: 0.015000s textrtype SLEEP(3) payload: 0.016840s shortcodepageid SLEEP(3) payload: 0.014518s Result: no candidate produced a timing delay on the fixed control. Response dbcall fields show injected quotes are escaped (backslash-quoted) where string-filter candidates are concatenated, while the numeric notinstring payload is neutralized by the integer-casting patch. This is a negative variant result, not a confirmed bypass. [17:12:52] RESULT: NO DISTINCT VARIANT/BYPASS CONFIRMED - original notinstring patch blocks original payload; tested alternate public fields were fast.