[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$ff_pRnKo-8loEf4oS8vEGUNDTxaWCSKAer4ez_NVNbOE":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":31,"poc_model_used":9,"poc_verification_depth":9,"source_links":41},"CVE-2026-4977","userswp-authenticated-subscriber-restricted-usermeta-modification-via-htmlvar-parameter","UsersWP \u003C= 1.2.58 - Authenticated (Subscriber+) Restricted Usermeta Modification via 'htmlvar' Parameter","The UsersWP – Front-end login form, User Registration, User Profile & Members Directory plugin for WordPress is vulnerable to Improper Access Control in all versions up to, and including, 1.2.58 This is due to insufficient field-level permission validation in the upload_file_remove() AJAX handler where the $htmlvar parameter is not validated against a whitelist of allowed fields or checked against the field's for_admin_use property. This makes it possible for authenticated attackers, with subscriber-level access and above, to clear or reset any restricted usermeta column for their own user record, including fields marked as \"For admin use only\", bypassing intended field-level access restrictions.","userswp",null,"\u003C=1.2.58","1.2.59","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-04-09 12:42:34","2026-04-10 01:25:00",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fefee685c-e2cd-471b-aea9-607124df6006?source=api-prod",1,[22,23,24,25,26,27,28,29],"admin\u002Fsettings\u002Fclass-formbuilder.php","assets\u002Fjs\u002Fusers-wp.js","assets\u002Fjs\u002Fusers-wp.min.js","includes\u002Fclass-forms.php","includes\u002Fclass-userswp.php","languages\u002Fuserswp-en_US.po","readme.txt","templates\u002Fbootstrap\u002Fmodal-profile-image-crop.php","researched",false,3,"# Research Plan: CVE-2026-4977 - Authenticated Usermeta Modification in UsersWP\n\n## 1. Vulnerability Summary\nThe **UsersWP** plugin (\u003C= 1.2.58) contains a flaw in its AJAX handling logic where an authenticated user (Subscriber level or higher) can clear or reset arbitrary `usermeta` fields for their own account. \n\nThe vulnerability exists in the `uwp_upload_file_remove` AJAX action (handled by `UsersWP_Ajax::upload_file_remove()`). The function accepts a user-controlled parameter `htmlvar` representing a metadata key. It fails to validate this key against an allowlist of permitted \"file\" fields or check if the field is flagged for administrative use only (`for_admin_use`). Consequently, an attacker can supply any meta key (e.g., `wp_capabilities`) to delete or reset its value.\n\n## 2. Attack Vector Analysis\n- **Endpoint**: `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Action**: `uwp_upload_file_remove`\n- **Vulnerable Parameter**: `htmlvar` (carries the target `usermeta` key)\n- **Authentication**: Required (Subscriber level is sufficient)\n- **Nonce Requirement**: Yes, the action requires a nonce typically localized as `uwp_localize_data.basicNonce`.\n- **Preconditions**: The attacker must be logged in and able to access a page where the UsersWP scripts are enqueued to retrieve the nonce.\n\n## 3. Code Flow\n1. **Entry Point**: The client sends a `POST` request to `admin-ajax.php` with `action=uwp_upload_file_remove`.\n2. **Hook Registration**: In `includes\u002Fclass-userswp.php`, the `UsersWP_Ajax` class is initialized. This class registers the AJAX handler:\n   `add_action( 'wp_ajax_uwp_upload_file_remove', array( $this, 'upload_file_remove' ) );`\n3. **Handler Execution** (`upload_file_remove`):\n   - It retrieves `security` (nonce), `htmlvar` (meta key), and `uid` (user ID) from `$_POST`.\n   - It verifies the nonce (likely against the action `uwp_basic_nonce`).\n   - It checks if the `uid` matches the current user or if the user has admin privileges.\n   - **Sink**: It proceeds to call `update_user_meta($uid, $htmlvar, '')` or `delete_user_meta($uid, $htmlvar)` without verifying if `$htmlvar` is a restricted field.\n4. **Impact**: The metadata field for the user is cleared.\n\n## 4. Nonce Acquisition Strategy\nThe nonce is localized in the front-end using `wp_localize_script` under the object `uwp_localize_data`.\n\n1. **Shortcode Identification**: The plugin uses the `[uwp_profile]` or `[uwp_account]` shortcodes to render user-facing forms where `users-wp.js` is loaded.\n2. **Page Creation**: Create a page containing the `[uwp_profile]` shortcode.\n3. **Extraction**:\n   - Navigate to the page as a logged-in Subscriber.\n   - Execute JavaScript via `browser_eval` to retrieve the nonce:\n     `browser_eval(\"uwp_localize_data.basicNonce\")`\n4. **JS Variable Verbatim**: `uwp_localize_data.basicNonce` (found in `assets\u002Fjs\u002Fusers-wp.js`).\n\n## 5. Exploitation Strategy\nThe goal is to clear a restricted usermeta field, such as `wp_capabilities` (to remove the user's role) or a custom UsersWP field intended for admin use.\n\n### Step-by-Step Plan:\n1. **Authentication**: Log in as a Subscriber user.\n2. **Nonce Retrieval**:\n   - Navigate to `\u002Fprofile-page\u002F` (created in setup).\n   - Capture the value of `uwp_localize_data.basicNonce`.\n3. **Target Selection**:\n   - Target: `wp_capabilities` (Standard WordPress restricted field).\n   - Target: `uwp_admin_note` (Inferred UsersWP meta field).\n4. **Exploit Request**:\n   Send a `POST` request to `admin-ajax.php`:\n   - **URL**: `http:\u002F\u002Fvulnerable-wp.local\u002Fwp-admin\u002Fadmin-ajax.php`\n   - **Headers**: `Content-Type: application\u002Fx-www-form-urlencoded`\n   - **Body**:\n     ```\n     action=uwp_upload_file_remove&htmlvar=wp_capabilities&uid=[CURRENT_USER_ID]&security=[NONCE]\n     ```\n5. **Observation**: The response should be a JSON object: `{\"success\": true}`.\n\n## 6. Test Data Setup\n1. **Target User**: A user with username `victim_sub` and role `subscriber`.\n2. **Landing Page**:\n   ```bash\n   wp post create --post_type=page --post_title=\"User Account\" --post_status=publish --post_content='[uwp_account]'\n   ```\n3. **Verification Meta**: Ensure the user has a capability set.\n   ```bash\n   wp user meta get [USER_ID] wp_capabilities\n   ```\n\n## 7. Expected Results\n- The AJAX request returns `{\"success\": true}`.\n- The `wp_capabilities` meta entry for the `victim_sub` user is deleted or set to an empty string.\n- The user effectively loses their role and permissions on the site.\n\n## 8. Verification Steps\n1. **CLI Check**:\n   ```bash\n   wp user meta get [USER_ID] wp_capabilities\n   ```\n   *Expected Output*: Empty or error indicating the key does not exist.\n2. **Role Check**:\n   ```bash\n   wp user get [USER_ID] --field=roles\n   ```\n   *Expected Output*: Empty string.\n\n## 9. Alternative Approaches\nIf `wp_capabilities` is protected by internal WordPress filters that UsersWP doesn't bypass, target UsersWP-specific fields created via the Form Builder (`admin\u002Fsettings\u002Fclass-formbuilder.php`).\n1. Create a custom field `uwp_verified_status` and set it to `1` for the user.\n2. Use the exploit to clear `uwp_verified_status`.\n3. Verify the field is removed via `wp user meta get`.","The UsersWP plugin for WordPress is vulnerable to unauthorized usermeta modification due to a lack of field-level validation in the 'uwp_upload_file_remove' AJAX handler. Authenticated attackers (Subscriber and above) can clear arbitrary usermeta fields for their own account, including restricted administrative fields like 'wp_capabilities', by manipulating the 'htmlvar' parameter.","\u002F\u002F assets\u002Fjs\u002Fusers-wp.js @ 1.2.58\n$( '.uwp_upload_file_remove' ).on( 'click', function( event ) {\n    event.preventDefault();\n\n    var htmlvar =  $( this ).data( 'htmlvar' );\n    var uid =  $( this ).data( 'uid' );\n\n    var data = {\n        'action': 'uwp_upload_file_remove',\n        'htmlvar': htmlvar,\n        'uid': uid,\n        'security': uwp_localize_data.basicNonce\n    };","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fuserswp\u002F1.2.58\u002Fadmin\u002Fsettings\u002Fclass-formbuilder.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fuserswp\u002F1.2.59\u002Fadmin\u002Fsettings\u002Fclass-formbuilder.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fuserswp\u002F1.2.58\u002Fadmin\u002Fsettings\u002Fclass-formbuilder.php\t2025-12-11 14:08:00.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fuserswp\u002F1.2.59\u002Fadmin\u002Fsettings\u002Fclass-formbuilder.php\t2026-03-30 08:27:26.000000000 +0000\n@@ -1818,7 +1818,7 @@\n                 'label'      => __( 'Validation Pattern', 'userswp' ) . uwp_help_tip( __( 'Enter regex expression for HTML5 pattern validation.', 'userswp' ) ),\n                 'type'       => 'text',\n                 'wrap_class' => uwp_advanced_toggle_class(),\n-                'value'      => addslashes_gpc( $value ), \u002F\u002F Keep slashes\n+                'value'      => wp_slash( $value ), \u002F\u002F Keep slashes\n             )\n         );\n \ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fuserswp\u002F1.2.58\u002Fassets\u002Fjs\u002Fusers-wp.js \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fuserswp\u002F1.2.59\u002Fassets\u002Fjs\u002Fusers-wp.js\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fuserswp\u002F1.2.58\u002Fassets\u002Fjs\u002Fusers-wp.js\t2026-02-19 15:06:48.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fuserswp\u002F1.2.59\u002Fassets\u002Fjs\u002Fusers-wp.js\t2026-03-30 08:27:26.000000000 +0000\n@@ -106,8 +106,9 @@\n         $( '.uwp_upload_file_remove' ).on( 'click', function( event ) {\n             event.preventDefault();\n \n-            var htmlvar =  $( this ).data( 'htmlvar' );\n-            var uid =  $( this ).data( 'uid' );\n+            var $this = $(this);\n+            var htmlvar =  $this.data( 'htmlvar' );\n+            var uid =  $this.data( 'uid' );\n \n             var data = {\n                 'action': 'uwp_upload_file_remove',\n@@ -116,17 +117,25 @@\n                 'security': uwp_localize_data.basicNonce\n             };\n \n+            if ($this.closest(\"form\").find('.uwp-field-error').length) {\n+                $this.closest(\"form\").find('.uwp-field-error').remove();\n+            }\n+\n             jQuery.ajax({\n                 url: uwp_localize_data.ajaxurl,\n                 type: 'POST',\n                 data: data,\n                 dataType: 'json'\n             }).done(function(res, textStatus, jqXHR) {\n-                if (typeof res == 'object' && res.success) {\n-                    $(\"#\"+htmlvar+\"_row\").find(\".uwp_file_preview_wrap\").remove();\n-                    $(\"#\"+htmlvar).closest(\"td\").find(\".uwp_file_preview_wrap\").remove();\n-                    if($('input[name='+htmlvar+']').data( 'is-required' )){\n-                        $('input[name='+htmlvar+']').prop('required',true);\n+                if (res && typeof res == 'object') {\n+                    if (res.success) {\n+                        $(\"#\"+htmlvar+\"_row\").find(\".uwp_file_preview_wrap\").remove();\n+                        $(\"#\"+htmlvar).closest(\"td\").find(\".uwp_file_preview_wrap\").remove();\n+                        if($('input[name='+htmlvar+']').data( 'is-required' )){\n+                            $('input[name='+htmlvar+']').prop('required',true);\n+                        }\n+                    } else if (res.data && typeof res.data == 'object' && res.data.message) {\n+                        $this.parent(\".uwp_file_preview_wrap\").append('\u003Cdiv class=\"uwp-field-error\">' + res.data.message + '\u003C\u002Fdiv>');\n                     }\n                 }\n             });\n... (truncated)","The exploit targets the 'uwp_upload_file_remove' AJAX action, which is intended to allow users to remove uploaded files by clearing a specific usermeta key. \n\n1. Authentication: The attacker logs into the WordPress site with a Subscriber account.\n2. Nonce Acquisition: The attacker navigates to their own profile or account page to retrieve the required AJAX nonce stored in 'uwp_localize_data.basicNonce'.\n3. Payload Construction: The attacker crafts a POST request to '\u002Fwp-admin\u002Fadmin-ajax.php' with the following parameters:\n    - 'action': 'uwp_upload_file_remove'\n    - 'htmlvar': The target usermeta key (e.g., 'wp_capabilities' or any 'for_admin_use' field).\n    - 'uid': The attacker's own user ID.\n    - 'security': The captured 'basicNonce'.\n4. Execution: Because the server-side handler fails to validate that the provided 'htmlvar' corresponds to an actual file field or an authorized metadata key, the plugin executes 'delete_user_meta' or 'update_user_meta' on the sensitive key, effectively clearing it for the attacker's account.","gemini-3-flash-preview","2026-04-16 16:15:06","2026-04-16 16:15:35",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","1.2.58","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fuserswp\u002Ftags\u002F1.2.58","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fuserswp.1.2.58.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fuserswp\u002Ftags\u002F1.2.59","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fuserswp.1.2.59.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fuserswp\u002Ftags"]