CVE-2026-0550

myCred <= 2.9.7.3 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'mycred_load_coupon' Shortcode

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

Description

The myCred plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's 'mycred_load_coupon' shortcode in all versions up to, and including, 2.9.7.3 due to insufficient input sanitization and output escaping on user supplied attributes. 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<=2.9.7.3
PublishedFebruary 13, 2026
Last updatedFebruary 14, 2026
Affected pluginmycred

Source Code

WordPress.org SVN
Research Plan
Unverified

## Vulnerability Research Plan: CVE-2026-0550 ### 1. Vulnerability Summary The myCred plugin (up to version 2.9.7.3) is vulnerable to **Stored Cross-Site Scripting (XSS)**. This issue exists within the `mycred_load_coupon` shortcode. The plugin fails to adequately sanitize or escape user-provided a…

Show full research plan

Vulnerability Research Plan: CVE-2026-0550

1. Vulnerability Summary

The myCred plugin (up to version 2.9.7.3) is vulnerable to Stored Cross-Site Scripting (XSS). This issue exists within the mycred_load_coupon shortcode. The plugin fails to adequately sanitize or escape user-provided attributes within this shortcode before rendering them on the page. An authenticated user with Contributor level access (or higher) can embed malicious scripts into a post or page using these attributes. When any user (including administrators) views the affected page, the script executes in their browser context.

2. Attack Vector Analysis

  • Endpoint: WordPress Post/Page Editor (/wp-admin/post-new.php or via REST API).
  • Vulnerable Component: The mycred_load_coupon shortcode handler.
  • Trigger: Shortcode attribute values (e.g., class, id, or placeholder).
  • Authentication: Requires Contributor+ privileges (the ability to create or edit posts).
  • Payload Location: The shortcode is stored in the post_content field of the wp_posts table.

3. Code Flow (Inferred)

  1. Registration: The plugin registers the shortcode during the init hook:
    add_shortcode( 'mycred_load_coupon', '...' ); (likely in includes/mycred-shortcodes.php or similar).
  2. Processing: When a post is viewed, WordPress calls do_shortcode(), which triggers the registered callback function for mycred_load_coupon.
  3. Attribute Handling: The callback function extracts attributes using shortcode_atts().
  4. Vulnerable Sink: The extracted attributes (e.g., $atts['class']) are concatenated directly into an HTML string (e.g., a <div> or <input> tag) and returned to the renderer without using escaping functions like esc_attr() or esc_html().
  5. Rendering: The unsanitized HTML is output to the browser.

4. Nonce Acquisition Strategy

This is a Stored XSS vulnerability where the payload is delivered via post content.

  • Placement: No specific plugin-level nonce is required to place the shortcode in a post; the attacker relies on the standard WordPress post creation/editing capability.
  • AJAX Interaction (If applicable): If the mycred_load_coupon shortcode functions by rendering a button that triggers an AJAX call to load a coupon (the mycred_load_coupon action), we should check for a nonce in that AJAX call.
    • Inferred JS Variable: myCredLoadCoupon or mycred_vars.
    • Inferred Nonce Key: nonce or mycred_load_coupon_nonce.
  • Strategy for PoC Agent:
    1. The agent will first attempt to exploit the direct rendering of the shortcode attribute.
    2. If the XSS fires only on an interaction (like clicking a button rendered by the shortcode), the agent will navigate to the page and use browser_eval to find any localized nonces if needed for subsequent AJAX-based XSS steps.

5. Exploitation Strategy

  1. Authentication: Log in as a user with the Contributor role.
  2. Payload Selection: Use a classic attribute breakout payload.
    • Payload A (Attribute Breakout): [mycred_load_coupon class='"><script>alert(document.domain)</script>']
    • Payload B (Event Handler): [mycred_load_coupon class='x" onmouseover="alert(1)" style="width:1000px;height:1000px;display:block;"']
  3. Injection: Use wp post create to generate a page containing the payload.
  4. Trigger: Navigate to the newly created page as an Administrator.
  5. Verification: Check if the script executes (e.g., by observing an alert or verifying the presence of the unescaped script tag in the DOM via browser_eval).

6. Test Data Setup

  • User: Create a user with the contributor role.
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
  • Post: Create a draft or published post containing the malicious shortcode.
    wp post create --post_type=post --post_status=publish --post_title="Coupon Page" --post_author=$(wp user get attacker --field=ID) --post_content='[mycred_load_coupon class="\"><script>console.log(\"XSS_TRIGGERED\")</script>"]'

7. Expected Results

  • The HTTP response for the page view will contain the raw, unescaped string: <div class=""><script>console.log("XSS_TRIGGERED")</script>"> (or similar, depending on the exact HTML structure generated by the shortcode).
  • When viewed in a browser, the JavaScript console should display XSS_TRIGGERED.

8. Verification Steps

  1. Source Check: Retrieve the post content via WP-CLI to ensure the shortcode was saved correctly.
    wp post get <POST_ID> --field=post_content
  2. DOM Inspection: Use the browser_navigate and browser_eval tools to check if the script tag exists in the rendered HTML.
    browser_eval("document.body.innerHTML.includes('XSS_TRIGGERED')")
  3. Check for escaping: Verify that the output does NOT look like class="&quot;&gt;&lt;script&gt;...".

9. Alternative Approaches

  • Attribute Variations: If class is sanitized, try other potential attributes like id, placeholder, label, button_text, or url.
  • Shortcode Context: If the shortcode requires a valid coupon ID to render, first find or create a myCred coupon.
    • wp eval "mycred_create_coupon(array('code' => 'TEST123', 'amount' => 10));" (Note: This depends on internal myCred functions).
  • Bypass Filtering: If simple <script> tags are blocked by a WAF or basic filter, use event handlers:
    [mycred_load_coupon class='x" onfocus="alert(1)" autofocus="']
Research Findings
Static analysis — not yet PoC-verified

Summary

The myCred plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'mycred_load_coupon' shortcode in versions up to 2.9.7.3. Authenticated attackers with Contributor-level access or higher can inject arbitrary scripts into posts through unsanitized shortcode attributes such as 'class', which execute in the browser of any user viewing the page.

Exploit Outline

1. Log in to the WordPress dashboard with at least Contributor-level permissions. 2. Create a new post or edit an existing one via the Gutenberg editor or Classic editor. 3. Insert the 'mycred_load_coupon' shortcode with a malicious payload in an attribute, for example: [mycred_load_coupon class='"><script>alert(document.domain)</script>']. 4. Save the post as a draft or publish it. 5. Navigate to the public-facing URL of the post (or have an administrator view it). The script will execute because the plugin fails to escape the attribute value before rendering it in the HTML output.

Check if your site is affected.

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