-
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 3 commits
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 ); | ||
|
|
||
|
|
@@ -260,6 +260,13 @@ | |
| if ( ! $data ) { | ||
| return $vendor; | ||
| } | ||
| //Allow if current user is the vendor OR is an administrator/shop manager. | ||
| $is_owner = dokan_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 explicit check to block modifications to administrator accounts. According to issue #5286, the vulnerability allowed vendor staff to modify administrator accounts via the REST API, enabling account takeover through password reset. The recommended fix was to "block modifications to administrator accounts (return 403) before handling the email parameter." The current implementation prevents unauthorized users from updating arbitrary vendors, but doesn't explicitly check whether the target vendor ( 🔎 Proposed fix //Allow if current user is the vendor OR is an administrator/shop manager.
+$target_user = get_userdata( $vendor_id );
+if ( $target_user && in_array( 'administrator', $target_user->roles, true ) ) {
+ return new \WP_Error( 'dokan_permission_denied', __( 'Administrator accounts cannot be modified through this endpoint.', 'dokan-lite' ), [ 'status' => 403 ] );
+}
+
$is_owner = dokan_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' ) );
+ return new \WP_Error( 'dokan_permission_denied', __( 'You do not have permission to update this vendor.', 'dokan-lite' ), [ 'status' => 403 ] );
}🤖 Prompt for AI Agents |
||
|
|
||
| // default wp based user data | ||
| if ( ! empty( $data['user_pass'] ) && get_current_user_id() === $vendor->get_id() ) { | ||
|
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. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Description: Check for other uses of get_current_user_id vs dokan_get_current_user_id in Manager.php
# to understand the intended pattern.
# Search for get_current_user_id() usage
echo "=== Uses of get_current_user_id() ==="
rg -n 'get_current_user_id\(\)' includes/Vendor/Manager.php
echo ""
echo "=== Uses of dokan_get_current_user_id() ==="
rg -n 'dokan_get_current_user_id\(\)' includes/Vendor/Manager.php
# Check if password updates are intended to be restricted differently
echo ""
echo "=== Password update logic context ==="
rg -n -B2 -A2 'user_pass' includes/Vendor/Manager.phpRepository: getdokan/dokan Length of output: 1035 🏁 Script executed: #!/bin/bash
# Find the definition of dokan_get_current_user_id
echo "=== Definition of dokan_get_current_user_id() ==="
rg -n 'function\s+dokan_get_current_user_id' --type php
echo ""
echo "=== Broader search for dokan_get_current_user_id definition ==="
rg -B2 -A5 'dokan_get_current_user_id\s*=' --type php | head -30
echo ""
echo "=== Context around the permission check and password update ==="
sed -n '260,280p' includes/Vendor/Manager.phpRepository: getdokan/dokan Length of output: 1214 🏁 Script executed: #!/bin/bash
# Read the dokan_get_current_user_id function definition
sed -n '48,70p' includes/functions.php
echo ""
echo "=== Also check WordPress's get_current_user_id usage in this file ==="
rg -n 'get_current_user_id\(\)' includes/functions.php | head -10Repository: getdokan/dokan Length of output: 1330 Use The permission check at line 265 uses 🤖 Prompt for AI Agents |
||
|
|
@@ -383,7 +390,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