CVE-2025-14506

ConvertForce Popup Builder <= 0.0.7 - Stored Cross-Site Scripting via entrance_animation

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

Description

The ConvertForce Popup Builder plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the Gutenberg block's `entrance_animation` attribute in all versions up to, and including, 0.0.7. This is due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with Author-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<=0.0.7
PublishedJanuary 9, 2026
Last updatedJanuary 10, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2025-14506 - ConvertForce Popup Builder Stored XSS ## 1. Vulnerability Summary The **ConvertForce Popup Builder** plugin (<= 0.0.7) contains a stored Cross-Site Scripting (XSS) vulnerability within its Gutenberg block. The vulnerability resides in the handling of the `entrance_…

Show full research plan

Research Plan: CVE-2025-14506 - ConvertForce Popup Builder Stored XSS

1. Vulnerability Summary

The ConvertForce Popup Builder plugin (<= 0.0.7) contains a stored Cross-Site Scripting (XSS) vulnerability within its Gutenberg block. The vulnerability resides in the handling of the entrance_animation attribute. When a user with sufficient privileges (Author and above) saves a post containing this block, the value of entrance_animation is stored without proper sanitization. Upon rendering the post on the frontend, this value is output without adequate escaping, allowing for arbitrary JavaScript execution in the context of the victim's browser.

2. Attack Vector Analysis

  • Endpoint: WordPress REST API for Post/Page creation and updates (/wp-json/wp/v2/posts or /wp-json/wp/v2/pages).
  • Vulnerable Attribute: entrance_animation within the Gutenberg block (likely named convertforce-popup-builder/popup or similar).
  • Required Authentication: Author-level access or higher. Authors have the edit_posts and publish_posts capabilities, allowing them to use the Gutenberg editor and the REST API.
  • Preconditions: The plugin must be active, and the attacker must have credentials for an account with at least Author permissions.

3. Code Flow (Inferred)

  1. Registration: The plugin registers a Gutenberg block via register_block_type (PHP) or registerBlockType (JS).
  2. Attribute Definition: The block definition includes an attribute named entrance_animation.
  3. Storage: When a post is saved in the Gutenberg editor, the block's attributes are serialized into the post_content as JSON comments (e.g., <!-- wp:convertforce-popup-builder/popup {"entrance_animation":"..."} /-->).
  4. Rendering (Sink):
    • If it is a dynamic block: The plugin uses a render_callback function in PHP. This function retrieves the $attributes array and likely concatenates entrance_animation directly into an HTML string (e.g., <div class="cf-popup-container entrance-animation-<?php echo $attributes['entrance_animation']; ?>">) without using esc_attr().
    • If it is a static block: The save function in JavaScript generates the HTML. If the save function does not sanitize the attribute before including it in the returned JSX/HTML, the XSS is stored directly in the post_content and rendered by WordPress.
  5. Execution: When a victim views the published post, the browser parses the unescaped payload within the HTML attribute or tag, triggering the script.

4. Nonce Acquisition Strategy

To interact with the REST API for post creation/updates, a _wpnonce for the wp_rest action is required.

  1. Login: Authenticate as an Author user.
  2. Navigate to Admin: Access the WordPress dashboard (/wp-admin/).
  3. Extract Nonce: The wp_rest nonce is typically localized in the page source within the wpApiSettings object.
    • Tool: browser_eval
    • Script: window.wpApiSettings?.nonce
  4. Alternative: If the plugin enqueues specific scripts for its block, a nonce might also be available in a localized object like window.convertforce_builder_data?.nonce.

5. Exploitation Strategy

  1. Setup User: Create a user with the Author role.
  2. Get REST Nonce: Use browser_navigate to /wp-admin/post-new.php and browser_eval to get the wp_rest nonce.
  3. Craft Payload:
    • Gutenberg blocks store attributes in JSON within comments. The payload must break out of the HTML attribute where entrance_animation is rendered.
    • Target Payload: "><script>alert(document.domain)</script> (breaks out of a class or data attribute).
    • Alternative Payload: none" onmouseover="alert(1)" data-x=" (attribute breakout).
  4. Send REST Request: Use http_request to create a new post with the malicious block.
    • Method: POST
    • URL: https://[target]/wp-json/wp/v2/posts
    • Headers:
      • Content-Type: application/json
      • X-WP-Nonce: [extracted_nonce]
    • Body:
      {
        "title": "XSS Test Page",
        "content": "<!-- wp:convertforce-popup-builder/popup {\"entrance_animation\":\"\\\"><script>alert(document.domain)</script>\"} /-->",
        "status": "publish"
      }
      
      (Note: The block name convertforce-popup-builder/popup is an inference based on the plugin slug. This must be verified by inspecting the plugin's block.json or registration code if available).
  5. Trigger: Navigate to the URL of the newly created post (returned in the REST response).

6. Test Data Setup

  1. Plugin Installation: Ensure ConvertForce Popup Builder version 0.0.7 is installed and active.
  2. User Creation:
    • wp user create attacker attacker@example.com --role=author --user_pass=password123
  3. Identify Block Slug: Search the plugin directory for the block registration:
    • grep -r "register_block_type" .
    • grep -r "registerBlockType" .
    • Look for block.json files to find the exact name/slug.

7. Expected Results

  • The REST API returns a 201 Created response.
  • Upon visiting the post's permalink, the HTML source contains:
    <div ... class="... "><script>alert(document.domain)</script>">
  • An alert box appears showing the document domain.

8. Verification Steps

  1. Check Post Content: Use WP-CLI to verify the payload is stored exactly as sent.
    • wp post get [ID] --field=post_content
  2. Frontend Inspection: Fetch the rendered post and check for the unescaped script.
    • http_request GET https://[target]/path-to-post
    • Verify that esc_attr or esc_html was not applied to the entrance_animation value.

9. Alternative Approaches

  • Attribute Breakout: If the script is rendered inside a data- attribute or a class, try animation-name" onmouseover="alert(1).
  • Shortcode (if applicable): If the plugin also provides a shortcode equivalent (common for popup builders), test if the same attribute name is vulnerable in a shortcode: [convertforce_popup entrance_animation='"><script>alert(1)</script>'].
  • REST API Update: If creating a new post fails due to permissions, try updating an existing post owned by the Author.
    • POST /wp-json/wp/v2/posts/[id]
Research Findings
Static analysis — not yet PoC-verified

Summary

The ConvertForce Popup Builder plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'entrance_animation' attribute in its Gutenberg block. Authenticated attackers with Author-level access or higher can inject arbitrary JavaScript into posts by saving a crafted block attribute, which executes in the browser of any user viewing the page because the value is rendered without proper output escaping.

Exploit Outline

1. Authenticate as an Author or Editor to obtain the necessary privileges for post creation. 2. Access the WordPress admin dashboard and retrieve the REST API nonce (found in the 'wpApiSettings' object in the HTML source). 3. Craft a REST API request to create or update a post (POST to /wp-json/wp/v2/posts). 4. In the request body, set the 'content' field to include the ConvertForce Popup block with a malicious payload in the 'entrance_animation' attribute. A payload like '\"><script>alert(document.domain)</script>' is designed to break out of the HTML attribute context when the block is rendered. 5. Publish the post and navigate to its permalink. The injected script will execute in the browser of anyone viewing the post, including site administrators.

Check if your site is affected.

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