Skip to content

fix(security): prevent cross-vendor product-attribute editing via REST (IDOR)#3292

Open
MdAsifHossainNadim wants to merge 1 commit into
developfrom
fix/product-attribute-ownership-idor
Open

fix(security): prevent cross-vendor product-attribute editing via REST (IDOR)#3292
MdAsifHossainNadim wants to merge 1 commit into
developfrom
fix/product-attribute-ownership-idor

Conversation

@MdAsifHossainNadim

@MdAsifHossainNadim MdAsifHossainNadim commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

All Submissions:

  • My code follows the WordPress coding standards
  • My code is tested
  • My code has proper inline documentation

Changes proposed in this Pull Request:

Fixes a cross-vendor IDOR on the product-attribute edit / set-default REST routes: any authenticated vendor could modify the attributes of any other vendor's product.

What's the actual issue?

The custom routes
POST /wp-json/dokan/v1/products/attributes/edit-product/<id> and
POST /wp-json/dokan/v1/products/attributes/set-default/<id>
(where <id> is a product id) are both guarded by update_product_attribute_permissions_check(), which returned only:

return current_user_can( 'dokan_edit_product' );

dokan_edit_product is a primitive capability every vendor holds, and the check never looks at the product in the URL. So a vendor could pass another vendor's product id and overwrite that product's attributes / default attributes — the callbacks (update_product_attribute, update_product_default_attribute) load the product purely from the request id with no ownership check.

How we fixed itincludes/REST/ProductAttributeController.php

Gate the permission check on product ownership, exactly like the rest of Dokan (admins / shop managers exempt):

public function update_product_attribute_permissions_check( $request ) {
    // A vendor may only edit attributes on their own products; admins/shop managers are exempt.
    if ( ! current_user_can( 'manage_woocommerce' ) && ! dokan_is_product_author( absint( $request['id'] ) ) ) {
        return new WP_Error(
            'dokan_rest_cannot_edit',
            __( 'Sorry, you are not allowed to edit this product.', 'dokan-lite' ),
            array( 'status' => rest_authorization_required_code() )
        );
    }

    return current_user_can( 'dokan_edit_product' );
}

dokan_is_product_author() is Dokan's canonical "current user owns this product" primitive (vendor-staff aware). Both routes share this one permission callback, so both are fixed.

How to test

  1. As Vendor A, open one of your own products in the product editor, change an attribute / default attribute and save → it still works (no regression).
  2. As Vendor A, send a crafted request targeting Vendor B's product id:
    fetch('/wp-json/dokan/v1/products/attributes/edit-product/<VENDOR_B_PRODUCT_ID>', {
      method:'POST',
      headers:{'Content-Type':'application/json','X-WP-Nonce':window.dokan.rest.nonce},
      credentials:'same-origin',
      body: JSON.stringify({ attributes: [] })
    })
    • Before: 200 — Vendor B's product attributes are modified.
    • After: 403 dokan_rest_cannot_edit — request rejected. Same for /set-default/<id>.

Test result: ✅ Verified on a live install. As a non-admin vendor: requests to the vendor's own product id returned 200 (edit + set-default still work), while the same requests to another vendor's product id returned 403 dokan_rest_cannot_edit. Admins/shop managers are unaffected.

Related Pull Request(s)

  • Security audit tracking (finding L2): getdokan/plugin-internal-tasks#1994

Closes

  • Closes getdokan/plugin-internal-tasks#2000

Changelog entry

Fix — Cross-vendor product-attribute editing via REST

The product-attribute edit / set-default REST routes only checked a generic capability, so a vendor could edit another vendor's product attributes by passing a foreign product id. The permission check now verifies product ownership (admins and shop managers are exempt).

…t-default routes (IDOR)

The dokan/v1 products/attributes/edit-product/<id> and /set-default/<id> routes
guarded only on the generic dokan_edit_product capability, so any authenticated
vendor could modify another vendor's product attributes by passing a foreign
product id. The permission check now verifies product ownership via
dokan_is_product_author(); admins and shop managers (manage_woocommerce) are
exempt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

update_product_attribute_permissions_check() in ProductAttributeController.php gains an early authorization gate: users without manage_woocommerce who are not the product author (dokan_is_product_author) receive a WP_Error with code dokan_rest_cannot_edit before the existing capability check is evaluated.

Changes

Product Attribute REST Authorization

Layer / File(s) Summary
Ownership check in permission gate
includes/REST/ProductAttributeController.php
Non-manage_woocommerce users are now rejected with WP_Error('dokan_rest_cannot_edit', ...) unless dokan_is_product_author(absint($request['id'])) returns true; the pre-existing current_user_can('dokan_edit_product') return is unchanged.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~5 minutes

Possibly related PRs

  • getdokan/dokan#3274: Also adds dokan_is_product_author(...) ownership checks to REST permission methods to prevent vendors from operating on other vendors' products.

Suggested labels

urgent

Suggested reviewers

  • mrabbani

🐇 A gate was added, a wall stood tall,
No vendor shall edit another's hall!
"Are you the author?" the code now asks,
Only the owner may carry such tasks.
Hop along safely, one product at a time! 🌟

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the security fix and the affected REST product-attribute editing flow.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description covers the required change summary, testing, related issue, and changelog, with only some optional template sections omitted.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/product-attribute-ownership-idor

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@MdAsifHossainNadim MdAsifHossainNadim self-assigned this Jul 2, 2026
@MdAsifHossainNadim MdAsifHossainNadim added Needs: Testing This requires further testing Needs: Dev Review It requires a developer review and approval labels Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs: Dev Review It requires a developer review and approval Needs: Testing This requires further testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant