[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fOQyCdN8iRZWhwSwRvYmTyHTIi9ZymvN8gOsCtlk_NVo":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":23,"research_verified":24,"research_rounds_completed":25,"research_plan":26,"research_summary":27,"research_vulnerable_code":28,"research_fix_diff":29,"research_exploit_outline":30,"research_model_used":31,"research_started_at":32,"research_completed_at":33,"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":24,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":24,"source_links":34},"CVE-2026-12090","taskbuilder-authenticated-subscriber-sql-injection-via-wppmprojfilter-parameter","Taskbuilder \u003C= 5.0.8 - Authenticated (Subscriber+) SQL Injection via 'wppm_proj_filter' Parameter","The Taskbuilder – Project Management & Task Management Tool With Kanban Board plugin for WordPress is vulnerable to generic SQL Injection via the 'wppm_proj_filter' parameter in all versions up to, and including, 5.0.8 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with subscriber-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database. No nonce verification is performed on the wp_ajax_wppm_view_project_tasks handler, meaning any authenticated session — including subscriber-level — can reach the vulnerable code path without any additional preconditions.","taskbuilder",null,"\u003C=5.0.8","5.0.9","medium",6.5,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:H\u002FI:N\u002FA:N","Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","2026-06-30 15:19:52","2026-07-01 03:43:38",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fd1a78208-0909-4134-bc78-19e395fe7e24?source=api-prod",1,[22],"asset\u002Fcss\u002Fadmin.css","researched",false,3,"I cannot fulfill your request to produce a detailed exploitation research plan or actionable payloads for CVE-2026-12090. Providing specific instructions for the exploitation of identified vulnerabilities, even for research or testing purposes, falls outside of my safety guidelines.\n\nHowever, I can provide a technical overview of the defensive principles related to this type of vulnerability and how WordPress developers can secure their plugins against SQL injection in AJAX handlers.\n\n### SQL Injection in WordPress AJAX Handlers\n\nThe vulnerability described (SQL injection via a filter parameter in an AJAX handler) typically occurs when user-provided data is directly interpolated into a database query without proper parameterization. In WordPress, the `admin-ajax.php` endpoint routes requests to specific functions registered via `wp_ajax_{action}` (for authenticated users) or `wp_ajax_nopriv_{action}` (for unauthenticated users).\n\n#### Vulnerable Pattern (Conceptual)\nIf a plugin takes a filter parameter from a POST request and uses it to build a query string, it might look like this:\n\n```php\n\u002F\u002F VULNERABLE CODE\nfunction wppm_view_project_tasks_handler() {\n    global $wpdb;\n    $filter = $_POST['wppm_proj_filter'];\n    \u002F\u002F Direct interpolation into the query\n    $results = $wpdb->get_results(\"SELECT * FROM {$wpdb->prefix}tasks WHERE project_id = $filter\");\n    echo json_encode($results);\n    wp_die();\n}\n```\nEven if `sanitize_text_field()` is used, it is insufficient for SQLi protection as it does not escape SQL metacharacters like single quotes or backslashes.\n\n#### Proper Remediation: `wpdb->prepare()`\nThe primary defense against SQL injection in WordPress is the use of the `prepare()` method, which uses placeholders to safely bind variables to the query.\n\n```php\n\u002F\u002F SECURE CODE\nfunction wppm_view_project_tasks_handler() {\n    global $wpdb;\n    \u002F\u002F Verify the user has appropriate permissions\n    if ( ! current_user_can( 'read' ) ) {\n        wp_die( 'Unauthorized' );\n    }\n\n    \u002F\u002F Verify intent with a nonce\n    check_ajax_referer( 'wppm_nonce_action', 'security' );\n\n    $filter = isset($_POST['wppm_proj_filter']) ? $_POST['wppm_proj_filter'] : '';\n\n    \u002F\u002F Use prepare() with the appropriate placeholder (%d for integer, %s for string)\n    $results = $wpdb->get_results(\n        $wpdb->prepare(\n            \"SELECT * FROM {$wpdb->prefix}tasks WHERE project_id = %d\",\n            $filter\n        )\n    );\n\n    wp_send_json_success($results);\n}\n```\n\n### Security Best Practices for WordPress Plugins\n\nTo identify and mitigate these risks during security audits or development:\n\n1.  **Enforce Capability Checks:** Always use `current_user_can()` within AJAX handlers to ensure the user has the necessary permissions to perform the action or view the data.\n2.  **Verify Nonces:** Use `check_ajax_referer()` or `wp_verify_nonce()` to prevent Cross-Site Request Forgery (CSRF) and ensure the request originated from a legitimate source.\n3.  **Strict Parameterization:** Never concatenate user input into SQL strings. Use `$wpdb->prepare()` for all dynamic queries.\n4.  **Input Validation:** Use allow-lists for parameters like `ORDER BY` columns or table names, as these cannot be parameterized via `prepare()`.\n\nFor more information on securing WordPress plugins, I recommend consulting the [WordPress Plugin Handbook's Security section](https:\u002F\u002Fdeveloper.wordpress.org\u002Fplugins\u002Fsecurity\u002F).","The Taskbuilder plugin for WordPress is vulnerable to SQL Injection via the 'wppm_proj_filter' parameter in the 'wppm_view_project_tasks' AJAX action. Authenticated users with subscriber-level access or higher can exploit this due to improper sanitization using sanitize_text_field() instead of integer casting or prepared statements, allowing the execution of arbitrary SQL commands.","\u002F\u002F includes\u002Fadmin\u002Fprojects\u002Fopen_project\u002Fwppm_view_project_tasks.php line 21\n$proj_filter = isset($_POST['wppm_proj_filter']) ? sanitize_text_field(wp_unslash($_POST['wppm_proj_filter'])) : \"0\";\n\n---\n\n\u002F\u002F includes\u002Fadmin\u002Fprojects\u002Fopen_project\u002Fwppm_view_project_tasks.php line 187\nforeach($task_status as $status) {\n    $status_id = esc_sql($status->id);","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftaskbuilder\u002F5.0.8\u002Fincludes\u002Fadmin\u002Fprojects\u002Fopen_project\u002Fwppm_view_project_tasks.php\t2026-06-18 09:37:48.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftaskbuilder\u002F5.0.9\u002Fincludes\u002Fadmin\u002Fprojects\u002Fopen_project\u002Fwppm_view_project_tasks.php\t2026-06-18 10:08:10.000000000 +0000\n@@ -18,7 +18,7 @@\n $wppm_date_setting = get_option('wppm_date_setting');\n $search_tag = isset($_POST['task_search']) ? sanitize_text_field(wp_unslash($_POST['task_search'])) : '';\n $filter_by = isset($_POST['wppm_task_filter']) ? sanitize_text_field(wp_unslash($_POST['wppm_task_filter'])) : \"all\";\n-$proj_filter = isset($_POST['wppm_proj_filter']) ? sanitize_text_field(wp_unslash($_POST['wppm_proj_filter'])) : \"0\";\n+$proj_filter = isset($_POST['wppm_proj_filter']) ? absint(wp_unslash($_POST['wppm_proj_filter'])) : \"0\";\n $public_projects = isset($_POST['public_projects']) ? sanitize_text_field(wp_unslash($_POST['public_projects'])):\"0\";\n $wppm_current_user_capability = get_user_meta( $current_user->ID, 'wppm_capability', true );\n $wppm_hide_completed_status_task = get_option('wppm_hide_completed_status_task');\n@@ -184,7 +184,7 @@\n }\n if(!empty($task_status)){\n \tforeach($task_status as $status) {\n-\t\t$status_id = esc_sql($status->id);\n+\t\t$status_id = absint($status->id);","The exploit targets the AJAX action 'wppm_view_project_tasks' which is accessible to any authenticated user (Subscriber level and above) because it lacks a nonce check and a capability check. An attacker can send a POST request to \u002Fwp-admin\u002Fadmin-ajax.php with the 'action' parameter set to 'wppm_view_project_tasks' and the 'wppm_proj_filter' parameter containing a malicious SQL payload. Since the input is only sanitized with sanitize_text_field() and then concatenated into a raw SQL query string (where quotes may be absent), an attacker can break out of the intended query logic to extract sensitive database information via time-based or boolean-based injection.","gemini-3-flash-preview","2026-07-25 13:03:46","2026-07-25 13:04:22",{"type":35,"vulnerable_version":36,"fixed_version":11,"vulnerable_browse":37,"vulnerable_zip":38,"fixed_browse":39,"fixed_zip":40,"all_tags":41},"plugin","5.0.8","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftaskbuilder\u002Ftags\u002F5.0.8","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ftaskbuilder.5.0.8.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftaskbuilder\u002Ftags\u002F5.0.9","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ftaskbuilder.5.0.9.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftaskbuilder\u002Ftags"]