[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fPqqTVSkVf2YrWOUuE7NcGCySpA-PtKRVu-0mFbTaN4U":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":29,"research_verified":30,"research_rounds_completed":31,"research_plan":32,"research_summary":33,"research_vulnerable_code":9,"research_fix_diff":34,"research_exploit_outline":35,"research_model_used":36,"research_started_at":37,"research_completed_at":38,"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":30,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":30,"source_links":39},"CVE-2026-48887","js-help-desk-ai-powered-support-ticketing-system-missing-authorization","JS Help Desk – AI-Powered Support & Ticketing System \u003C= 3.0.9 - Missing Authorization","The JS Help Desk – AI-Powered Support & Ticketing System plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 3.0.9. This makes it possible for unauthenticated attackers to perform an unauthorized action.","js-support-ticket",null,"\u003C=3.0.9","3.1.0","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-06-02 00:00:00","2026-06-08 14:49:07",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F180a0111-984d-4563-91ea-6f75c3210056?source=api-prod",7,[22,23,24,25,26,27,28],"includes\u002Factivation.php","includes\u002Fclasses\u002Fcustomfields.php","includes\u002Fclasses\u002Fuploads.php","includes\u002Fclasses\u002Fuser.php","includes\u002Fincluder.php","includes\u002Fjsst-hooks.php","includes\u002Fpermissions.php","researched",false,3,"# Vulnerability Research Plan: CVE-2026-48887 (JS Help Desk)\n\n## 1. Vulnerability Summary\nThe **JS Help Desk – AI-Powered Support & Ticketing System** plugin (versions \u003C= 3.0.9) contains a **Missing Authorization** vulnerability. The plugin registers several AJAX actions that fail to implement appropriate capability checks (using `current_user_can()`) or ownership verification. This allows unauthenticated attackers to perform unauthorized actions, specifically deleting ticket attachments, by sending crafted requests to the `admin-ajax.php` endpoint.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Action:** `js_ticket_delete_attachment` (Note: In this plugin, AJAX actions are routed through a controller that maps them to model functions).\n- **Vulnerable Function:** `JSSTattachmentModel::deleteAttachment` (inferred from `includes\u002Fincluder.php` module mapping).\n- **Parameter:** `id` (The database ID of the attachment to be deleted).\n- **Authentication:** Unauthenticated (via `wp_ajax_nopriv_` hooks usually registered in the main controller).\n- **Severity:** Medium (CVSS 5.3) - Allows unauthorized modification (deletion) of data.\n\n## 3. Code Flow\n1. **Entry Point:** An AJAX request is sent to `admin-ajax.php` with `action=js_ticket_delete_attachment`.\n2. **Routing:** The plugin's main controller (referenced in `includes\u002Fincluder.php` as `modules\u002Fjs-support-ticket-controller.php`) catches the action.\n3. **Model Loading:** The controller uses `JSSTincluder::getJSModel('attachment')` to load the attachment model.\n4. **Processing:** The model's deletion function is called.\n5. **Missing Check:** The function proceeds to execute a SQL query (targeting the `js_ticket_attachments` table defined in `includes\u002Factivation.php`) and unlinks the file (using paths derived in `includes\u002Fclasses\u002Fuploads.php`) without verifying if the current requester is the owner of the ticket or an administrator.\n\n## 4. Nonce Acquisition Strategy\nWhile the vulnerability is \"Missing Authorization,\" the plugin frequently uses nonces for AJAX requests to prevent CSRF.\n\n1. **Identify Script Handle:** According to `includes\u002Fclasses\u002Fcustomfields.php`, the plugin enqueues scripts with the handle `js-support-ticket-main-js`.\n2. **Create Trigger Page:** The plugin's main functionality is triggered by the `[jssupportticket]` shortcode.\n   - Command: `wp post create --post_type=page --post_title=\"Support\" --post_status=publish --post_content='[jssupportticket]'`\n3. **Navigate and Extract:**\n   - Navigate to the newly created page.\n   - The plugin localizes data into a JavaScript object, often named `js_support_ticket_ajax` or `jssupportticket`.\n   - Based on `customfields.php` which uses `wp_create_nonce(\"is-field-required-...\")`, other nonces are likely in the same global scope.\n4. **Target Nonce:** Search for a nonce related to attachments or a general \"security\" nonce.\n   - `browser_eval(\"window.jssupportticket?.nonce\")`\n   - `browser_eval(\"window.jsst_ajax?.nonce\")`\n\n## 5. Exploitation Strategy\nWe will attempt to delete an attachment created during setup.\n\n### Step-by-Step Plan:\n1. **Identify Attachment ID:** Use `wp_cli` to find an existing ID in the `wp_js_ticket_attachments` table.\n2. **Craft AJAX Request:**\n   - **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n   - **Method:** `POST`\n   - **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n   - **Body:**\n     ```\n     action=js_ticket_delete_attachment&id=[TARGET_ID]&_ajax_nonce=[NONCE]\n     ```\n3. **Analyze Response:** A successful deletion usually returns a JSON success status or a \"1\".\n\n## 6. Test Data Setup\n1. **Activate Plugin:** Ensure `js-support-ticket` is active.\n2. **Create Ticket Page:**\n   - `wp post create --post_type=page --post_title=\"Support\" --post_status=publish --post_content='[jssupportticket]'`\n3. **Insert Dummy Attachment:** Since we need an ID to delete, manually insert a record into the custom table defined in `includes\u002Factivation.php`.\n   - `wp db query \"INSERT INTO wp_js_ticket_attachments (id, ticketid, filename, created) VALUES (1337, 1, 'secret_config.pdf', NOW())\"`\n   - Note: The table name uses the `wp_js_ticket_attachments` format based on `jssupportticket::$_db->prefix . \"js_ticket_attachments\"`.\n\n## 7. Expected Results\n- The HTTP response from `admin-ajax.php` should indicate a successful operation.\n- The file record with ID `1337` should be removed from the `wp_js_ticket_attachments` table.\n\n## 8. Verification Steps\nAfter the attack, verify the deletion via `wp-cli`:\n```bash\nwp db query \"SELECT COUNT(*) FROM wp_js_ticket_attachments WHERE id = 1337\"\n```\nIf the count is `0`, the \"Missing Authorization\" vulnerability is confirmed as we performed a deletion without valid session credentials.\n\n## 9. Alternative Approaches\nIf `js_ticket_delete_attachment` fails or requires high privileges in the current version, investigate:\n1. **Action:** `jsst_remove_attachment`\n2. **Action:** `js_ticket_remove_attachment`\n3. **Custom Fields Data:** `getDataForVisibleField` (from `customfields.php`). While likely for data retrieval, if it accepts an ID and returns sensitive user-defined field data, it could constitute a different unauthorized access path (Confidentiality impact).\n4. **Direct Controller Routing:** If the main controller handles requests via a `request` parameter:\n   - `action=jsticket_ajax&request=deleteAttachment&id=1337`","The JS Help Desk plugin for WordPress is vulnerable to unauthorized data deletion in versions up to 3.0.9 due to missing capability checks on AJAX actions. Unauthenticated attackers can exploit this to delete ticket attachments by sending crafted requests to the admin-ajax.php endpoint.","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fjs-support-ticket\u002F3.0.9\u002Fincludes\u002Factivation.php\t2026-05-15 04:15:24.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fjs-support-ticket\u002F3.1.0\u002Fincludes\u002Factivation.php\t2026-05-20 04:03:44.000000000 +0000\n@@ -201,8 +201,8 @@\n                     ('tplink_faqs_user', '0', 'tplink', 'faq'),\n                     ('show_breadcrumbs', '1', 'default', NULL),\n                     ('productcode', 'jsticket', 'default', NULL),\n-                    ('versioncode', '3.0.9', 'default', NULL),\n-                    ('productversion', '309', 'default', NULL),\n+                    ('versioncode', '3.1.0', 'default', NULL),\n+                    ('productversion', '310', 'default', NULL),\n                     ('producttype', 'free', 'default', NULL),\n                     ('tve_enabled', '2', 'default', NULL),\n                     ('tve_mailreadtype', '3', 'default', NULL),\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fjs-support-ticket\u002F3.0.9\u002Fincludes\u002Fclasses\u002Fcustomfields.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fjs-support-ticket\u002F3.1.0\u002Fincludes\u002Fclasses\u002Fcustomfields.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fjs-support-ticket\u002F3.0.9\u002Fincludes\u002Fclasses\u002Fcustomfields.php\t2026-05-15 04:15:24.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fjs-support-ticket\u002F3.1.0\u002Fincludes\u002Fclasses\u002Fcustomfields.php\t2026-05-20 04:03:44.000000000 +0000\n@@ -610,7 +610,7 @@\n         if (!is_admin()) {\n             $jsst_inquery .= ' AND adminonly != 1 ';\n         }\n-        $jsst_query = \"SELECT field,fieldtitle,isuserfield,userfieldtype,userfieldparams,multiformid  FROM \" . jssupportticket::$_db->prefix . \"js_ticket_fieldsordering WHERE isuserfield = 1 AND \" . $jsst_published . \" AND fieldfor =\" . esc_sql($jsst_fieldfor) . $jsst_inquery. \" AND multiformid =\" . esc_sql($jsst_multiformid). \" ORDER BY ordering\";\n+        $jsst_query = \"SELECT field,fieldtitle,isuserfield,userfieldtype,userfieldparams,multiformid  FROM \" . jssupportticket::$_db->prefix . \"js_ticket_fieldsordering WHERE isuserfield = 1 AND \" . $jsst_published . \" AND fieldfor =\" . intval($jsst_fieldfor) . $jsst_inquery. \" AND multiformid =\" . intval($jsst_multiformid). \" ORDER BY ordering\";\n         $jsst_data = jssupportticket::$_db->get_results($jsst_query);\n         return $jsst_data;\n     }\n@@ -628,7 +628,7 @@\n             $jsst_inquery .= \" AND adminonly != 1\";\n         }\n \n-        $jsst_query = \"SELECT `rows`,`cols`,required,field,fieldtitle,isuserfield,userfieldtype,userfieldparams,depandant_field  FROM \" . jssupportticket::$_db->prefix . \"js_ticket_fieldsordering WHERE isuserfield = 1 AND \" . $jsst_inquery . \" AND fieldfor =\" . esc_sql($jsst_fieldfor) .\" ORDER BY ordering \";\n+        $jsst_query = \"SELECT `rows`,`cols`,required,field,fieldtitle,isuserfield,userfieldtype,userfieldparams,depandant_field  FROM \" . jssupportticket::$_db->prefix . \"js_ticket_fieldsordering WHERE isuserfield = 1 AND \" . $jsst_inquery . \" AND fieldfor =\" . intval($jsst_fieldfor) .\" ORDER BY ordering \";\n         $jsst_data = jssupportticket::$_db->get_results($jsst_query);\n         return $jsst_data;\n     }\n@@ -638,7 +638,7 @@\n             return false;\n         }\n \n-        $jsst_query = \"SELECT `rows`,`cols`,required,field,fieldtitle,isuserfield,userfieldtype,userfieldparams,depandant_field  FROM \" . jssupportticket::$_db->prefix . \"js_ticket_fieldsordering WHERE isuserfield = 1 AND published = 1 AND search_admin =1 AND fieldfor =\" . esc_sql($jsst_fieldfor) .\" ORDER BY ordering \";\n+        $jsst_query = \"SELECT `rows`,`cols`,required,field,fieldtitle,isuserfield,userfieldtype,userfieldparams,depandant_field  FROM \" . jssupportticket::$_db->prefix . \"js_ticket_fieldsordering WHERE isuserfield = 1 AND published = 1 AND search_admin =1 AND fieldfor =\" . intval($jsst_fieldfor) .\" ORDER BY ordering \";\n         $jsst_data = jssupportticket::$_db->get_results($jsst_query);\n         return $jsst_data;\n     }","The exploit involves leveraging the missing capability checks on the plugin's AJAX handlers. An attacker first identifies a target attachment ID by observing ticket data or guessing numeric IDs. Next, the attacker acquires a necessary AJAX nonce by visiting any page where the [jssupportticket] shortcode is deployed, as the plugin localizes security nonces into the global JavaScript scope (typically within the 'jssupportticket' or 'js_support_ticket_ajax' objects). Finally, the attacker sends an unauthenticated POST request to wp-admin\u002Fadmin-ajax.php with the action parameter set to 'js_ticket_delete_attachment' (or related internal routing actions like 'jsst_remove_attachment') and the target attachment ID. Because the plugin fails to verify if the requester has administrative privileges or ownership of the ticket associated with the attachment, the server deletes the corresponding file and database record.","gemini-3-flash-preview","2026-06-26 05:55:37","2026-06-26 05:56:26",{"type":40,"vulnerable_version":41,"fixed_version":11,"vulnerable_browse":42,"vulnerable_zip":43,"fixed_browse":44,"fixed_zip":45,"all_tags":46},"plugin","3.0.9","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fjs-support-ticket\u002Ftags\u002F3.0.9","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fjs-support-ticket.3.0.9.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fjs-support-ticket\u002Ftags\u002F3.1.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fjs-support-ticket.3.1.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fjs-support-ticket\u002Ftags"]