CVE-2026-8441: Verified Reproduction
CVE-2026-8441: WP Review Slider Pro SQL injection
CVE-2026-8441 is verified against the affected target. Vulnerability class: SQLi. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00239.
What Is CVE-2026-8441?
CVE-2026-8441 is a high-severity, unauthenticated SQL injection vulnerability in the WP Review Slider Pro WordPress plugin, reachable via the 'noti' (notinstring) parameter. Pruva reproduced it (reproduction REPRO-2026-00239).
CVE-2026-8441 Severity & CVSS Score
CVE-2026-8441 is rated high severity, with a CVSS base score of 7.5 out of 10.
High — serious impact or readily exploitable. Prioritize remediation.
How to Reproduce CVE-2026-8441
pruva-verify REPRO-2026-00239 curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00239/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-8441
- reached the target end-to-end
- on the real production code path
- high confidence
- the upstream fix blocks the same trigger
HTTP POST field notinstring (ticket abbreviation: noti) in wprp_load_more_revs admin-ajax.php action
- POST /wp-admin/admin-ajax.php action=wprp_load_more_revs with public nonce and notinstring=1) OR (SELECT SLEEP(5))#
How the agent worked
Root Cause and Exploit Chain for CVE-2026-8441
CVE-2026-8441 is an unauthenticated SQL injection vulnerability in the WP Review Slider Pro WordPress plugin. The vulnerable public AJAX action is wprp_load_more_revs, reached through /wp-admin/admin-ajax.php from a public page rendering the plugin shortcode. The genuine WP Review Slider Pro 12.6.7 code reads the request field notinstring in WP_Review_Pro_Public::wppro_loadmore_revs_ajax(), passes it through sanitize_text_field(), and later concatenates it into an unquoted numeric AND id NOT IN (...) SQL fragment in GetReviews_Functions::wppro_queryreviews(). The reproduction proves the issue against a live WordPress/MariaDB service using the genuine plugin source zip, with time-based and conditional extraction payloads, and then proves a line-accurate fixed patch makes the same endpoint fast.
- Package/component affected: WP Review Slider Pro (Premium), WordPress plugin slug/codebase
wp-review-slider-pro; public AJAX actionwprp_load_more_revs; vulnerable helperpublic/partials/getreviews_class.php. - Affected versions: Public advisory states versions up to and including 12.7.2. The runtime proof uses a genuine WP Review Slider Pro (Premium) 12.6.7 source zip (
sha256: 7f6092f4ea58b5c5c0dba72ba014b9395bf9608f9aeeb95206e80dc14f0b17e5), which contains the vulnerable line-accurate code path. - Risk level and consequences: High. An unauthenticated attacker who can access a public page rendering a WP Review Slider Pro template can send a POST to WordPress
admin-ajax.phpand inject SQL into the plugin's review query. The reproduced consequence is blind SQL injection sufficient to infer database contents via conditional delays, demonstrated by extracting the first character of the WordPress admin username.
Impact Parity
- Disclosed/claimed maximum impact: SQL injection with ability to extract database data remotely and unauthenticated.
- Reproduced impact from this run: Full remote API reachability and blind SQL injection. The script demonstrates normal fast response (~0.106s), repeated
SLEEP(5)delays (~5.03s and ~5.02s),SLEEP(3)delay (~3.02s), and a conditional extraction oracle whereadminusername first-character test foradelays (~3.02s) while the falsextest is fast (~0.016s). - Parity:
fullfor the SQL injection/data-extraction claim. - Not demonstrated: Bulk dumping of the entire database was not performed; the proof stops after a minimal conditional data-extraction primitive to avoid unnecessary exposure. Code execution was not claimed or demonstrated.
Root Cause
The root cause is insufficient SQL neutralization of an attacker-controlled request parameter in a public AJAX handler:
WP_Review_Pro_Public::wppro_loadmore_revs_ajax()is registered for both authenticated and unauthenticated users viawp_ajax_wprp_load_more_revsandwp_ajax_nopriv_wprp_load_more_revs.- The handler performs a nonce check, but the nonce is exposed to public visitors by
wp_localize_script()on frontend pages rendering[wprevpro_usetemplate]. - The handler reads
$_POST['notinstring']and appliessanitize_text_field(). This WordPress text sanitizer is not an SQL escaping or parameterization mechanism; it does not remove SQL operators such as) OR (SELECT SLEEP(...))#. - In
public/partials/getreviews_class.php, the plugin callsexplode(',', $notinstring)and immediately rejoins the array withimplode(',', $tempnotinarray), then buildsAND id NOT IN ($notinstring)by string concatenation. - The resulting query is executed by
$wpdb->get_results()without a prepared statement or integer casting for theNOT INlist.
The line-accurate patch used in the fixed control changes the vulnerable line to cast the CSV list through absint before it is rejoined:
$tempnotinarray = array_filter(array_map('absint', explode(",", $notinstring)));
This preserves numeric review IDs while removing SQL syntax from the NOT IN list. The public advisory names fixed version 12.7.3; no public source commit was available because the plugin is distributed commercially.
Reproduction Steps
- Run
bundle/repro/reproduction_steps.sh. - The script:
- verifies the bundled genuine WP Review Slider Pro 12.6.7 zip and records source identity;
- installs/uses PHP, MariaDB, WordPress, and WP-CLI;
- activates the genuine plugin in a live WordPress instance;
- seeds real plugin tables with review/template data and publishes a page containing
[wprevpro_usetemplate tid="1"]; - retrieves the public nonce from that page;
- sends real HTTP POST requests to
/wp-admin/admin-ajax.phpwithaction=wprp_load_more_revs, the nonce, and attacker-controllednotinstringpayloads (the request also includesnotifor ticket terminology, but the genuine plugin consumesnotinstring); - captures vulnerable timing and response artifacts;
- patches the genuine product file in place with a line-accurate integer-casting fix;
- restarts the PHP service and proves the same payload is fast after patching.
- Expected evidence of reproduction:
- vulnerable
SLEEP(5)requests take approximately five seconds twice; - vulnerable conditional true extraction takes approximately three seconds while the false condition is fast;
- fixed
SLEEP(5)attempts are fast after the patch; - response JSON contains
dbcallfields showing injected SQL before the patch and sanitizedAND id NOT IN (1)after the patch.
- vulnerable
Evidence
- Primary runtime log:
bundle/logs/reproduction_steps.log - Evidence summary:
bundle/logs/evidence.log - Runtime manifest:
bundle/repro/runtime_manifest.json - Timing summary:
bundle/artifacts/timing_summary.json - Vulnerable HTTP responses:
bundle/artifacts/vuln_sleep5_attempt1_response.jsonbundle/artifacts/vuln_sleep5_attempt2_response.jsonbundle/artifacts/vuln_data_true_response.jsonbundle/artifacts/vuln_data_false_response.json
- Fixed HTTP responses:
bundle/artifacts/fixed_sleep5_warmup_response.jsonbundle/artifacts/fixed_sleep5_attempt1_response.jsonbundle/artifacts/fixed_sleep5_attempt2_response.json
- Source identity and patch evidence:
bundle/logs/plugin_source_identity.logbundle/logs/real_notinstring_patch.diffbundle/artifacts/real_vulnerable_getreviews_excerpt.txtbundle/artifacts/real_ajax_handler_excerpt.txt
Key runtime evidence from the final verified run:
Endpoint: POST http://127.0.0.1:36179/wp-admin/admin-ajax.php
Action: wprp_load_more_revs
Nonce source: public page rendering [wprevpro_usetemplate tid="1"]
Vulnerable timings:
normal notinstring=1,2,3: 0.106269s
SLEEP(5) attempt 1: 5.028141s
SLEEP(5) attempt 2: 5.018714s
SLEEP(3): 3.017385s
conditional user_login first char == 'a': 3.016486s
conditional user_login first char == 'x': 0.015544s
Fixed patched-product timings:
SLEEP(5) warmup after patch (ignored): 0.046941s
SLEEP(5) attempt 1: 0.016054s
SLEEP(5) attempt 2: 0.015599s
normal: 0.016293s
The runtime manifest records entrypoint_kind="api_remote", service_started=true, healthcheck_passed=true, and target_path_reached=true.
Recommendations / Next Steps
- Update WP Review Slider Pro to version 12.7.3 or later.
- Apply integer allow-listing/casting to every numeric
IN/NOT INlist built from request data; usingarray_map('absint', ...)is appropriate for review ID lists. - Prefer
$wpdb->prepare()for all dynamic SQL, and avoid concatenating request-controlled strings into SQL fragments. - Add regression tests for
wprp_load_more_revswith maliciousnotinstringvalues such as1) OR (SELECT SLEEP(5))#, verifying the resulting query contains only numeric IDs and has no timing delay. - Audit related AJAX handlers in the same plugin for similar array/CSV-to-SQL concatenation patterns.
Additional Notes
- The script was run successfully twice consecutively after fixes, confirming idempotency in a clean runtime directory under
bundle/artifacts/runtime. - The ticket text abbreviates the affected parameter as
noti; the real WP Review Slider Pro code and public advisories identify the consumed parameter asnotinstring. The reproduction includes thenotifield in requests for traceability, but the genuine plugin's vulnerable sink is$_POST['notinstring']. - The fixed control is a line-accurate local patch to the same genuine product file because a public vendor git commit was not available for the commercial plugin.
CVE-2026-8441 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.
Full session Replay every step — scrub the timeline or play it back.
echo "=== Check WordPress.org API for wp-review-slider-pro ===" && curl -s "https://api.wordpress.org/plugins/info/1.0/wp-review-slider-pro.json" 2>/dev/null | head -c 2000; echo; echo "=== Check for wp-review-slider (free) ===" && curl -s "https://api.wordpress.org/plugins/info/1.0/wp-review-slider.json" 2>/dev/null | head -c 2000; echo; echo "=== Check for wp-reviews ===" && curl -s "https://api.wordpress.org/plugins/info/1.0/wp-reviews.json" 2>/dev/null | head -c 1000=== Check WordPress.org API for wp-review-slider-pro ===
{"error":"Plugin not found."}
=== Check for wp-review-slider (free) ===
{"error":"Plugin not found."}
=== Check for wp-reviews ===
{"error":"Plugin not found."}Artifacts and Evidence for CVE-2026-8441
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-8441
FAQ: CVE-2026-8441
How does the CVE-2026-8441 SQL injection attack work?
How severe is CVE-2026-8441?
How can I reproduce CVE-2026-8441?
References for CVE-2026-8441
Authoritative sources for CVE-2026-8441 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.