Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-97286 — Technical advisory and proof of concept for CVE-2026-97286, an authenticated stored XSS in the WordPress Strong Testimonials plugin, with attack chain, PoC and patch analysis. | Kitploit
Tools/GitHubGitHub/rully2212/cve-2026-97286
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPapers & ResearchLearning & Education
GitHubrully2212/cve-2026-97286

CVE-2026-97286

Technical advisory and proof of concept for CVE-2026-97286, an authenticated stored XSS in the WordPress Strong Testimonials plugin, with attack chain, PoC and patch analysis.

View Repository
1 month agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-97286: Authenticated Stored XSS in Strong Testimonials

An authenticated Contributor can store attacker-controlled platform photo metadata in the WordPress Strong Testimonials plugin. Before version 3.3.12, the plugin rendered the stored value inside an image src attribute without contextual escaping. After an administrator publishes the crafted testimonial and a post that displays it, the payload executes for visitors who open that post, including unauthenticated visitors.

This research was performed in an authorized local lab and disclosed through Patchstack before public release.

Advisory metadata

FieldValue
CVECVE-2026-97286
ProductStrong Testimonials
VendorWP Chill
Plugin slugstrong-testimonials
VulnerabilityAuthenticated stored cross-site scripting
Affected versions<= 3.3.11
Patched version3.3.12
Required privilegeContributor or higher
CWECWE-79: Improper Neutralization of Input During Web Page Generation
CVSS v3.16.5 Medium — CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:L
ResearcherRully Miftahur Rozaq
ReportedSeptember 16, 2026
Public disclosureSeptember 30, 2026

Patchstack classifies the advisory as low priority even though the assigned CVSS v3.1 base severity is Medium.

Summary

The testimonial editor accepts a custom request array and persists every submitted key as post metadata. Keys not present in the configured custom-field definition fall through to sanitize_text_field(). This allows a Contributor to submit plugin-reserved metadata such as platform and platform_user_photo while editing a testimonial they own.

For supported social platforms, the plugin retrieves platform_user_photo, verifies that the URL returns an HTTP 200 response, and then interpolates the original stored string into an <img src="https://raw.githubusercontent.com/rully2212/cve-2026-97286/main/..."> attribute. HTTP status validation does not make a string safe for an HTML attribute. A quotation mark in the URL fragment can terminate src and introduce an event handler.

The verified attack chain is:

  1. A Contributor saves crafted platform photo metadata in a testimonial they own.
  2. An administrator publishes the testimonial and a normal post that renders it.
  3. The plugin emits the crafted value as part of an image tag.
  4. JavaScript executes in the site origin when a visitor opens the published post.

The injection is authenticated. The visitor who triggers the already-published payload does not need to be authenticated.

Impact

Successful exploitation provides persistent JavaScript execution in the affected WordPress origin on pages that render the crafted testimonial through the vulnerable thumbnail path. Code executes with the browser privileges and WordPress session of the visitor, if any.

The reproduced path requires administrator publication, which accounts for the CVSS UI:R metric. This research did not demonstrate unauthenticated injection, automatic execution across every site page, privilege escalation, cookie theft, or full site compromise.

Tested environment

The proof of concept was reproduced with the following configuration:

ComponentConfiguration
WordPress7.1
Strong Testimonials3.3.7, free edition
ThemeTwenty Twenty-Five
Display templatedefault-theme
ThumbnailEnabled
PHP / ApachePHP 8.3.33 / Apache 2.4.68
DatabaseMariaDB 11.4
Attacker roleContributor
Attacker capabilitiesedit_posts=true, publish_posts=false, unfiltered_html=false

Version 3.3.7 was the exact version used in the lab. The public CVE record identifies all versions through 3.3.11 as affected and version 3.3.12 as fixed.

Technical analysis

1. Unexpected metadata keys are persisted

In admin/class-strong-testimonials-post-editor.php, save_details() iterates over every entry in the submitted custom array. An unrecognized key reaches the generic sanitization branch and is then stored with update_post_meta():

$custom = $_POST['custom'];

foreach ( $custom as $key => $value ) {
    // ...
    $sanitized_value = sanitize_text_field( $value );
    update_post_meta( $post_id, $key, $sanitized_value );
}

The real handler performs nonce checks and field-specific sanitization. The finding does not rely on bypassing those checks or editing another user's testimonial. The Contributor legitimately edits their own testimonial but supplies the reserved keys platform and platform_user_photo.

2. HTTP status validation is not output escaping

In vulnerable versions, includes/functions-image.php reads platform_user_photo, performs an HTTP status check through wpmtst_is_valid_image_url(), and inserts the original string into an HTML attribute:

$platform_user_photo = get_post_meta( $post_id, 'platform_user_photo', true );
if ( ! $platform_user_photo || ! wpmtst_is_valid_image_url( $platform_user_photo ) ) {
    return $img;
}

return sprintf(
    '<img src="https://raw.githubusercontent.com/rully2212/cve-2026-97286/main/%25s" %s %s/>',
    $platform_user_photo,
    $width ? "width='{$width}'" : '',
    $height ? "height='{$height}'" : ''
);

The fragment portion of a URL is not sent to the HTTP server, but it remains in the string later rendered by PHP. The server can therefore see a harmless URL returning HTTP 200 while the browser receives a value containing an attribute-breakout sequence.

3. The frontend template trusts the generated image HTML

The default-theme template calls wpmtst_get_thumbnail() and directly emits the returned image markup:

<figure class="wp-block-image wpmtst-testimonial-avatar">
    <?php echo $wpmtst_avatar_html; ?>
</figure>

The template assumes the helper has already produced safe HTML. In affected versions, the platform photo helper did not escape the URL for its src context.

Proof of concept

Only reproduce this issue on a system you own or are explicitly authorized to test.

Prerequisites

  • Strong Testimonials <= 3.3.11 on an authorized WordPress test site.
  • A standard Contributor account.
  • A Strong Testimonials Display view using default-theme with thumbnails enabled.
  • An administrator account for the normal publication step.

Steps

  1. Sign in as the Contributor and create a new testimonial draft.

  2. Capture the legitimate POST /wp-admin/post.php save request using an intercepting proxy. Keep its complete form body, session cookie, fresh WordPress nonce, plugin nonce, and the ID of the Contributor-owned testimonial.

  3. Append these parameters to the form body:

    custom[platform]=facebook
    custom[platform_user_photo]=http://wordpress/index.php?rest_route=/#" onerror="alert(1)" x="
    

    URL-encoded form fragment:

    &custom%5Bplatform%5D=facebook&custom%5Bplatform_user_photo%5D=http%3A%2F%2Fwordpress%2Findex.php%3Frest_route%3D%2F%23%22%20onerror%3D%22alert%281%29%22%20x%3D%22
    

    The wordpress hostname is the Docker service name used in the local lab. In another authorized environment, replace it with a researcher-controlled test endpoint that is reachable by WordPress and returns HTTP 200. Do not target third-party or sensitive internal services.

  4. Send the modified save request and submit the testimonial for review.

  5. Create a normal WordPress post containing a Shortcode block. Replace the example IDs with the Display view ID and crafted testimonial ID from the test installation:

    [testimonial_view id="2" post_ids="22" thumbnail="1"]
    
Download Tool