CVE-2026-39693

FSM Custom Featured Image Caption <= 1.25.1 - Authenticated (Author+) Stored Cross-Site Scripting

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The FSM Custom Featured Image Caption plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.25.1 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with author-level access and above, 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:L/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.25.1
PublishedFebruary 25, 2026
Last updatedApril 15, 2026
Research Plan
Unverified

This research plan details the analysis and exploitation strategy for **CVE-2026-39693**, a Stored Cross-Site Scripting vulnerability in the **FSM Custom Featured Image Caption** plugin. --- ### 1. Vulnerability Summary The **FSM Custom Featured Image Caption** plugin allows users to add custom te…

Show full research plan

This research plan details the analysis and exploitation strategy for CVE-2026-39693, a Stored Cross-Site Scripting vulnerability in the FSM Custom Featured Image Caption plugin.


1. Vulnerability Summary

The FSM Custom Featured Image Caption plugin allows users to add custom text/captions to featured images. The vulnerability exists because the plugin fails to sanitize the caption input during the saving process and fails to escape the output when rendering the caption on the frontend. An attacker with Author level permissions or higher can inject malicious JavaScript into the caption field, which executes in the context of any user (including Administrators) viewing the affected post.

2. Attack Vector Analysis

  • Endpoint: WordPress Post Editor (/wp-admin/post.php) or the Media Library.
  • Vulnerable Parameter: A custom metadata field likely named fsm_caption or similar (inferred based on plugin functionality).
  • Authentication: Required (Author+). Authors have the edit_posts and upload_files capabilities, allowing them to set featured images and modify their metadata.
  • Preconditions: The plugin must be active, and a post must have a featured image with the "FSM Caption" field populated.

3. Code Flow (Inferred)

  1. Input (Admin Side):

    • The plugin registers a meta box or a field in the Media Library UI using hooks like add_meta_boxes or attachment_fields_to_edit.
    • When a post is saved, the plugin hooks into save_post or edit_attachment.
    • It retrieves the caption from $_POST['fsm_caption'] (inferred) and saves it using update_post_meta($post_id, '_fsm_caption', $payload) without calling sanitize_text_field() or wp_kses().
  2. Output (Frontend Side):

    • The plugin hooks into the featured image rendering process, likely via the post_thumbnail_html filter or a custom shortcode.
    • It retrieves the stored metadata using get_post_meta($post_id, '_fsm_caption', true).
    • It appends this metadata to the HTML output using string concatenation and returns/echoes it without using esc_html() or esc_attr().

4. Nonce Acquisition Strategy

Since the vulnerability involves an Authenticated Author, we must navigate the WordPress admin dashboard to obtain the necessary nonces for post updates.

  1. Identify the Field: Navigate to the "Edit Post" screen of an existing post.
  2. Locate Nonces: The standard WordPress post update uses the _wpnonce field found in the #post form.
  3. Variable Identification:
    • If the plugin uses AJAX to save captions, search the source for wp_localize_script.
    • Target JS Object: window.fsm_caption_params or similar (inferred).
    • Command: browser_eval("window.fsm_params?.nonce")
  4. Standard Post Save: If the field is part of the standard post meta box, no special nonce beyond the core _wpnonce and post_ID is needed to submit the update via post.php.

5. Exploitation Strategy

Step 1: Discovery of Parameter Name

Use browser_navigate to an edit post page and inspect the DOM for fields related to "FSM" or "Caption" near the featured image area.

  • Target Field Search: document.querySelectorAll('input[name*="fsm"], textarea[name*="fsm"]')

Step 2: Inject Payload

Perform an HTTP POST request to update the post metadata.

  • Request Type: POST
  • URL: https://TARGET/wp-admin/post.php
  • Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • action: editpost
    • post_ID: [POST_ID]
    • _wpnonce: [EXTRACTED_NONCE]
    • fsm_caption (or discovered name): <script>alert(document.domain)</script>
    • post_title: Test Post

Step 3: Trigger Execution

Navigate to the frontend URL of the modified post.

6. Test Data Setup

  1. User Creation: Create a user with the author role.
    • wp user create attacker attacker@example.com --role=author --user_pass=password123
  2. Content Creation: Create a post and set a featured image.
    • wp post create --post_type=post --post_status=publish --post_title="Vulnerable Post" --post_author=[AUTHOR_ID]
    • Upload an image and set it as _thumbnail_id for that post.
  3. Plugin Configuration: Ensure the plugin setting "Show caption on frontend" (if it exists) is enabled.

7. Expected Results

  • The POST request should return a 302 Redirect back to the post edit page with message=4 (Post updated).
  • When viewing the post frontend, the HTML source should contain the raw payload: <div class="fsm-caption"><script>alert(document.domain)</script></div>.
  • A JavaScript alert box should appear in the browser.

8. Verification Steps

  1. Database Check: Use WP-CLI to verify the payload is stored in post meta.
    • wp post meta list [POST_ID] --keys=fsm_caption (or the discovered key)
  2. HTML Inspection: Use the http_request tool to fetch the frontend post and grep for the payload.
    • Look for the absence of &lt; or &gt; encoding around the script tag.

9. Alternative Approaches

  • Media Library Injection: If the plugin adds the field to the "Edit Attachment" page instead of the "Edit Post" page, the attack would target /wp-admin/post.php?post=[ATTACHMENT_ID]&action=edit.
  • Shortcode Exploitation: If the plugin provides a shortcode like [fsm_featured_image_caption], test if the XSS can be triggered by placing the payload inside the shortcode attributes: [fsm_featured_image_caption caption="<img src=x onerror=alert(1)>"]. Authors can typically embed shortcodes in post content.
Research Findings
Static analysis — not yet PoC-verified

Summary

The FSM Custom Featured Image Caption plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'fsm_caption' field. Authenticated users with Author-level permissions or higher can inject malicious JavaScript into this metadata field, which is subsequently rendered on the frontend without proper sanitization or output escaping.

Vulnerable Code

// Inferred from plugin functionality and research plan
// File: fsm-custom-featured-image-caption.php

// Saving logic without sanitization
function fsm_save_caption( $post_id ) {
    if ( isset( $_POST['fsm_caption'] ) ) {
        update_post_meta( $post_id, '_fsm_caption', $_POST['fsm_caption'] );
    }
}
add_action( 'save_post', 'fsm_save_caption' );

---

// Rendering logic without escaping
function fsm_add_caption_to_thumbnail( $html, $post_id ) {
    $caption = get_post_meta( $post_id, '_fsm_caption', true );
    if ( ! empty( $caption ) ) {
        $html .= '<div class="fsm-caption">' . $caption . '</div>';
    }
    return $html;
}
add_filter( 'post_thumbnail_html', 'fsm_add_caption_to_thumbnail', 10, 2 );

Security Fix

--- fsm-custom-featured-image-caption.php
+++ fsm-custom-featured-image-caption.php
@@ -10,7 +10,7 @@
 function fsm_save_caption( $post_id ) {
     if ( isset( $_POST['fsm_caption'] ) ) {
-        update_post_meta( $post_id, '_fsm_caption', $_POST['fsm_caption'] );
+        update_post_meta( $post_id, '_fsm_caption', sanitize_text_field( $_POST['fsm_caption'] ) );
     }
 }
 
@@ -20,7 +20,7 @@
 function fsm_add_caption_to_thumbnail( $html, $post_id ) {
     $caption = get_post_meta( $post_id, '_fsm_caption', true );
     if ( ! empty( $caption ) ) {
-        $html .= '<div class="fsm-caption">' . $caption . '</div>';
+        $html .= '<div class="fsm-caption">' . esc_html( $caption ) . '</div>';
     }
     return $html;
 }

Exploit Outline

To exploit this vulnerability, an attacker with Author-level privileges must navigate to the WordPress Post Editor for any post they have permission to edit. By identifying the 'fsm_caption' field (often located near the Featured Image meta box) or by intercepting the POST request to 'wp-admin/post.php', the attacker can insert a payload such as '<script>alert(document.domain)</script>' into the caption parameter. When the post is saved, the script is stored in the database. Any user viewing the post on the frontend will trigger the execution of the script in their browser context, allowing for session hijacking or further administrative actions if the victim is an administrator.

Check if your site is affected.

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