fix(security): prevent cross-vendor download-permission granting in grant_access_to_download (IDOR)#3293
Conversation
…(IDOR) The grant_access_to_download AJAX handler verified order ownership but then looped attacker-controlled product_ids and granted download permissions for any product, so a vendor could grant their customer download access to another vendor's downloadable files. Skip products the current vendor does not own (dokan_is_product_author); the added null guard also removes a latent null-dereference on invalid product ids. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 42 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
All Submissions:
Changes proposed in this Pull Request:
Fixes a cross-vendor IDOR in the "grant download access" AJAX handler: a vendor could grant a customer download permissions for another vendor's downloadable files.
What's the actual issue?
grant_access_to_download()(wp_ajax_dokan_grant_access_to_download) verifies the nonce, thedokandarcapability, anddokan_is_seller_has_order( current_user, order_id )— i.e. it confirms the vendor owns the order. It then loops over the attacker-controlled$_POST['product_ids']and callswc_downloadable_file_permission()for each, without checking that the vendor owns those products:So a vendor could send another vendor's downloadable product id and grant their own customer free, working download permissions for that vendor's paid files. (The unchecked
$productalso fataled on an invalid id.)How we fixed it —
includes/Ajax.phpSkip any product the current vendor does not own before granting:
dokan_is_product_author()is Dokan's canonical product-ownership primitive (vendor-staff aware); the same! $productguard also removes the pre-existing null-dereference on invalid ids.How to test
product_ids(actiondokan_grant_access_to_download, validgrant-accessnonce, your ownorder_id).woocommerce_downloadable_product_permissionsrow is created for the foreign product — the customer can download another vendor's file.Test result: ✅ Verified on a live install by replaying the handler's exact (patched) grant loop as a non-admin vendor against one of the vendor's own orders: the vendor's own product took the grant path, while a foreign vendor's downloadable product was skipped and zero download-permission rows were created for it. (This is a legacy admin-ajax handler whose UI only renders for orders that contain the vendor's own downloadable products, so it was exercised through the server-side handler path rather than the browser.)
Related Pull Request(s)
Closes
Changelog entry
Fix — Cross-vendor download-permission granting
The "grant download access" handler only checked order ownership, so a vendor could grant download permissions for another vendor's downloadable products by passing foreign product ids. Each product is now checked for ownership before access is granted.