-
Notifications
You must be signed in to change notification settings - Fork 214
fix(security): implement strict authorization for store settings update #3045
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
42e0fd9
54fc225
20e7c3f
ca2114e
42f7568
0c154af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -52,7 +52,7 @@ | |||||||||||||||||||||||||||||
| 'order' => 'ASC', | ||||||||||||||||||||||||||||||
| 'status' => [ 'approved' ], | ||||||||||||||||||||||||||||||
| 'featured' => '', // yes or no | ||||||||||||||||||||||||||||||
| 'meta_query' => [], | ||||||||||||||||||||||||||||||
| 'fields' => 'all', | ||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
@@ -69,7 +69,7 @@ | |||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| $meta_query[] = [ | ||||||||||||||||||||||||||||||
| 'key' => 'dokan_enable_selling', | ||||||||||||||||||||||||||||||
| 'value' => ( $stat == 'approved' ) ? 'yes' : 'no', | ||||||||||||||||||||||||||||||
| 'compare' => '=', | ||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
@@ -78,11 +78,11 @@ | |||||||||||||||||||||||||||||
| $args['meta_query']['relation'] = 'AND'; | ||||||||||||||||||||||||||||||
| $args['meta_query'][] = $meta_query; | ||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||
| $args['meta_query'] = $meta_query; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // if featured | ||||||||||||||||||||||||||||||
| if ( 'yes' == $args['featured'] ) { | ||||||||||||||||||||||||||||||
| $args['meta_query']['relation'] = 'AND'; | ||||||||||||||||||||||||||||||
| $args['meta_query'][] = [ | ||||||||||||||||||||||||||||||
| 'key' => 'dokan_feature_seller', | ||||||||||||||||||||||||||||||
|
|
@@ -168,7 +168,7 @@ | |||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @since 3.2.7 added $data parameter | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| $store_data = apply_filters( 'dokan_vendor_create_data', [ | ||||||||||||||||||||||||||||||
| 'store_name' => ! empty( $data['store_name'] ) ? $data['store_name'] : '', | ||||||||||||||||||||||||||||||
| 'social' => ! empty( $data['social'] ) ? $data['social'] : [], | ||||||||||||||||||||||||||||||
| 'payment' => ! empty( $data['payment'] ) ? $data['payment'] : [ | ||||||||||||||||||||||||||||||
|
|
@@ -187,7 +187,7 @@ | |||||||||||||||||||||||||||||
| 'show_min_order_discount' => ! empty( $data['show_min_order_discount'] ) ? $data['show_min_order_discount'] : 'no', | ||||||||||||||||||||||||||||||
| 'store_seo' => ! empty( $data['store_seo'] ) ? $data['store_seo'] : [], | ||||||||||||||||||||||||||||||
| 'dokan_store_time' => ! empty( $data['store_open_close'] ) ? $data['store_open_close'] : [], | ||||||||||||||||||||||||||||||
| ], $data ); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| $vendor = dokan()->vendor->get( $vendor_id ); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
@@ -261,6 +261,14 @@ | |||||||||||||||||||||||||||||
| return $vendor; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // Allow if current user is the vendor OR is an administrator/shop manager. | ||||||||||||||||||||||||||||||
| $is_owner = get_current_user_id() === (int) $vendor->get_id(); | ||||||||||||||||||||||||||||||
| $is_admin = current_user_can( 'manage_woocommerce' ) || current_user_can( 'manage_options' ); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if ( ! $is_owner && ! $is_admin ) { | ||||||||||||||||||||||||||||||
| return new \WP_Error( 'dokan_permission_denied', __( 'You do not have permission to update this vendor.', 'dokan-lite' ) ); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add HTTP 403 status code to the permission denied error. The permission check logic correctly addresses the IDOR vulnerability. However, the 🔎 Proposed fix if ( ! $is_owner && ! $is_admin ) {
- return new \WP_Error( 'dokan_permission_denied', __( 'You do not have permission to update this vendor.', 'dokan-lite' ) );
+ return new \WP_Error( 'dokan_permission_denied', __( 'You do not have permission to update this vendor.', 'dokan-lite' ), [ 'status' => 403 ] );
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // default wp based user data | ||||||||||||||||||||||||||||||
| if ( ! empty( $data['user_pass'] ) && get_current_user_id() === $vendor->get_id() ) { | ||||||||||||||||||||||||||||||
| wp_update_user( | ||||||||||||||||||||||||||||||
|
|
@@ -383,7 +391,7 @@ | |||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // for backward compatibility we'll allow both `enable_tnc` and `toc_enabled` to set store trams and condition settings | ||||||||||||||||||||||||||||||
| if ( ( isset( $data['enable_tnc'] ) && dokan_validate_boolean( $data['enable_tnc'] ) ) | ||||||||||||||||||||||||||||||
| || ( isset( $data['toc_enabled'] ) && dokan_validate_boolean( $data['toc_enabled'] ) ) ) { | ||||||||||||||||||||||||||||||
| $vendor->set_enable_tnc( 'on' ); | ||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||
| $vendor->set_enable_tnc( 'off' ); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: getdokan/dokan
Length of output: 1078
🏁 Script executed:
Repository: getdokan/dokan
Length of output: 2955
🏁 Script executed:
Repository: getdokan/dokan
Length of output: 1519
🏁 Script executed:
Repository: getdokan/dokan
Length of output: 2794
🏁 Script executed:
Repository: getdokan/dokan
Length of output: 3583
Verify vendor-ownership authorization for cross-vendor access scenarios.
The
check_permissionmethod fromVendorAuthorizableonly checkscurrent_user_can( 'dokandar' )without differentiating between read and write operations. More critically, bothget_settings()andupdate_settings()callbacks use the same permission check but lack explicit vendor-ownership validation when avendor_idparameter is provided. This allows any user with the 'dokandar' capability to potentially read and update other vendors' settings. Ensure the callbacks validate that users can only access/modify their own vendor's settings, or implement operation-specific permission checks.🤖 Prompt for AI Agents