You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi Dokan team — per support ticket #336995, posting here as requested.
Summary
Dokan Lite's REST bulk-order-actions endpoint lets any vendor change the status of another vendor's orders. The permission callback checks only that the caller holds the standard seller dokan_manage_order capability — it never verifies that the orders in the request actually belong to the caller. A seller can flip arbitrary marketplace orders to completed / processing / on-hold / etc., which fires WooCommerce's status-change emails to those customers and releases downloadable-product permissions.
Confirmed on WordPress + WooCommerce 10.9.4 + Dokan Lite 5.0.8.
Where
Route:POST /wp-json/dokan/v3/orders/bulk-actions (also /dokan/v2/...) — registered in includes/REST/OrderControllerV2.php (~L143–167).
Permission callback:update_order_permissions_check in includes/REST/OrderController.php (~L821–833) — checks current_user_can('dokan_manage_order') and that order_status_change is on (default). No per-order ownership check.
Handler:process_orders_bulk_action (OrderControllerV2.php ~L416–425) → dokan_apply_bulk_order_status_change (includes/Order/functions.php ~L953–981), which loops wc_get_order($order_id)->update_status($status) over the caller-supplied order_ids[] with no dokan_get_seller_id_by_order() author check.
Notably, every other order route does enforce ownership — the single-item update_item runs validation_before_update_item (OrderController.php ~L241–245), and the note routes compare dokan_get_seller_id_by_order() === current_user_id. The bulk path is the one that skips it, which is what points to this being an oversight rather than intended behavior.
Steps to reproduce
Two vendors: seller1 and seller2 (role seller; dokan_manage_order = yes, manage_woocommerce = no). seller2 owns order Author name is wrong on the cart #16.
As seller1, call POST /wp-json/dokan/v3/orders/bulk-actions with order_ids[]=16 and a status (e.g. completed).
Observed: the permission callback returns true, order Author name is wrong on the cart #16 goes pending → completed, and WooCommerce sends the completed-order email — even though seller1 is not the order's vendor (dokan_get_seller_id_by_order(16) returns seller2's id).
Impact
Horizontal cross-tenant access-control failure (CWE-862 / CWE-639). A vendor can tamper with the whole marketplace's order state: mark others' orders complete (releasing downloads + emailing those customers), revert others' completed orders, and disrupt fulfillment across all vendors. It does not reach admin, a role change, or any secret — so I'd rate it Medium.
Secondary (same class)
OrderControllerV2::revoke_order_downloads (OrderControllerV2.php ~L390–405) deletes a download permission by the caller-supplied permission_id without checking that the permission belongs to the order — the callback only verifies the order is the caller's. The sibling update_order_download (~L345) does check $download->get_order_id() === $order_id; the revoke path doesn't. So a vendor who owns one order can revoke arbitrary customers' download permissions.
Suggested fix
Add a per-order ownership check in dokan_apply_bulk_order_status_change (and in process_orders_bulk_action before it): for non-admins, filter order_ids to those where dokan_get_seller_id_by_order($id) === dokan_get_current_user_id(), mirroring validation_before_update_item. Apply the same ownership check to the revoke-downloads permission lookup.
Happy to clarify anything. Thanks for the responsive handling.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Hi Dokan team — per support ticket #336995, posting here as requested.
Summary
Dokan Lite's REST bulk-order-actions endpoint lets any vendor change the status of another vendor's orders. The permission callback checks only that the caller holds the standard seller
dokan_manage_ordercapability — it never verifies that the orders in the request actually belong to the caller. A seller can flip arbitrary marketplace orders tocompleted/processing/on-hold/ etc., which fires WooCommerce's status-change emails to those customers and releases downloadable-product permissions.Confirmed on WordPress + WooCommerce 10.9.4 + Dokan Lite 5.0.8.
Where
POST /wp-json/dokan/v3/orders/bulk-actions(also/dokan/v2/...) — registered inincludes/REST/OrderControllerV2.php(~L143–167).update_order_permissions_checkinincludes/REST/OrderController.php(~L821–833) — checkscurrent_user_can('dokan_manage_order')and thatorder_status_changeison(default). No per-order ownership check.process_orders_bulk_action(OrderControllerV2.php~L416–425) →dokan_apply_bulk_order_status_change(includes/Order/functions.php~L953–981), which loopswc_get_order($order_id)->update_status($status)over the caller-suppliedorder_ids[]with nodokan_get_seller_id_by_order()author check.Notably, every other order route does enforce ownership — the single-item
update_itemrunsvalidation_before_update_item(OrderController.php~L241–245), and the note routes comparedokan_get_seller_id_by_order() === current_user_id. The bulk path is the one that skips it, which is what points to this being an oversight rather than intended behavior.Steps to reproduce
seller1andseller2(roleseller;dokan_manage_order= yes,manage_woocommerce= no).seller2owns order Author name is wrong on the cart #16.seller1, callPOST /wp-json/dokan/v3/orders/bulk-actionswithorder_ids[]=16and a status (e.g.completed).true, order Author name is wrong on the cart #16 goespending → completed, and WooCommerce sends the completed-order email — even thoughseller1is not the order's vendor (dokan_get_seller_id_by_order(16)returns seller2's id).Impact
Horizontal cross-tenant access-control failure (CWE-862 / CWE-639). A vendor can tamper with the whole marketplace's order state: mark others' orders complete (releasing downloads + emailing those customers), revert others' completed orders, and disrupt fulfillment across all vendors. It does not reach admin, a role change, or any secret — so I'd rate it Medium.
Secondary (same class)
OrderControllerV2::revoke_order_downloads(OrderControllerV2.php~L390–405) deletes a download permission by the caller-suppliedpermission_idwithout checking that the permission belongs to the order — the callback only verifies the order is the caller's. The siblingupdate_order_download(~L345) does check$download->get_order_id() === $order_id; the revoke path doesn't. So a vendor who owns one order can revoke arbitrary customers' download permissions.Suggested fix
Add a per-order ownership check in
dokan_apply_bulk_order_status_change(and inprocess_orders_bulk_actionbefore it): for non-admins, filterorder_idsto those wheredokan_get_seller_id_by_order($id) === dokan_get_current_user_id(), mirroringvalidation_before_update_item. Apply the same ownership check to the revoke-downloads permission lookup.Happy to clarify anything. Thanks for the responsive handling.
All reactions