[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fgrYga6VQHZwBtmSA-SiapsBgufsGVUuwYfZ4T5ZP2bY":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-42655","paymattic-secure-simple-payment-donation-with-subscription-payments-recurring-donations-customer-management-missing-auth","Paymattic – Secure, Simple Payment & Donation with Subscription Payments, Recurring Donations, Customer Management \u003C= 4.6.19 - Missing Authorization","The Paymattic – Secure, Simple Payment & Donation with Subscription Payments, Recurring Donations, Customer Management plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 4.6.19. This makes it possible for unauthenticated attackers to perform an unauthorized action.","wp-payment-form",null,"\u003C=4.6.19","4.6.20","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-04-29 00:00:00","2026-05-04 14:06:06",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fe60cd9eb-5707-493d-8f3a-3d4160e14735?source=api-prod",6,[22,23,24,25,26,27,28,29],"app\u002FHooks\u002FHandlers\u002FAdminMenuHandler.php","app\u002FHooks\u002FHandlers\u002FSubmissionHandler.php","app\u002FHooks\u002FScheduler\u002FPendingPaymentExpirationHandler.php","app\u002FHooks\u002Factions.php","app\u002FHttp\u002FRoutes\u002Froutes.php","app\u002FModules\u002FBuilder\u002FRender.php","app\u002FModules\u002FBuilder\u002FSubscriptionEntries.php","app\u002FModules\u002FExterior\u002FProcessDemoPage.php","researched",false,3,"### 1. Vulnerability Summary\nThe Paymattic plugin (\u003C= 4.6.19) contains a **Missing Authorization** vulnerability within its custom routing system. Specifically, certain administrative or dashboard-level actions—such as canceling subscriptions or syncing billing data—were accessible through unauthenticated AJAX requests. \n\nThe vulnerability stems from the plugin's use of a custom router (defined in `app\u002FHttp\u002FRoutes\u002Froutes.php`) which dispatches requests to controllers based on a `route` parameter. In versions up to 4.6.19, routes within the `dashboard` prefix (intended for customers) and potentially some under `forms` were not strictly enforced against unauthenticated access, or the `FrontendUserPolicy` failed to validate that the requester was the owner of the entry.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Action:** `wppayform_api` or `wppayform_frontend_api` (dispatched via the `WPPayForm\\App\\Http\\Router`).\n*   **Vulnerable Route:** `dashboard\u002Fform\u002F{id}\u002Fentries\u002F{entryId}\u002Fcancel-subscription`\n*   **HTTP Method:** `POST`\n*   **Authentication:** Unauthenticated (`nopriv`).\n*   **Preconditions:** An existing submission\u002Fsubscription ID and form ID must be known (often sequential and easily guessable).\n\n### 3. Code Flow\n1.  The request hits `admin-ajax.","The Paymattic plugin for WordPress (\u003C= 4.6.19) lacks proper authorization checks and nonce validation within its custom routing system and AJAX handlers. This allows unauthenticated attackers to perform unauthorized actions, such as canceling subscriptions, accessing sensitive billing data, or submitting forged form data by targeting predictable form and entry IDs.","\u002F\u002F app\u002FHooks\u002Factions.php:145\nadd_action('wp_ajax_wpf_submit_form', array(new \\WPPayForm\\App\\Hooks\\Handlers\\SubmissionHandler(), 'handleSubmission'));\nadd_action('wp_ajax_nopriv_wpf_submit_form', array(new \\WPPayForm\\App\\Hooks\\Handlers\\SubmissionHandler(), 'handleSubmission'));\n\n---\n\n\u002F\u002F app\u002FHooks\u002FHandlers\u002FSubmissionHandler.php:33\nclass SubmissionHandler\n{\n    \u002F\u002F ... (omitted properties)\n    public function handleSubmission()\n    {\n        if (!isset($_REQUEST['form_data'])) {\n            return;\n        }\n   \n        parse_str($_REQUEST['form_data'], $form_data);\n        \u002F\u002F ...\n        if(isset($_REQUEST['form_id'])){\n            $formId = absint(sanitize_text_field(wp_unslash($_REQUEST['form_id'])));\n        }\n        \u002F\u002F No nonce verification or capability check performed before processing data\n\n---\n\n\u002F\u002F app\u002FHttp\u002FRoutes\u002Froutes.php:84\n$router->prefix('dashboard')->withPolicy('FrontendUserPolicy')->group(function ($router) {\n    $router->get('\u002Fforms\u002Fformatted', 'FormsController@formatted');\n    $router->prefix('\u002Fform\u002F{id}\u002Fentries')->group(function ($router) {\n        $router->prefix('\u002F{entryId}')->group(function ($router) {\n            $router->get('\u002F', 'SubmissionController@getSubmission')->int('id', 'entryId');\n            $router->post('\u002Fcancel-subscription', 'SubmissionController@cancelSubscription')->int('id', 'entryId');\n        });\n    });\n});","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-payment-form\u002F4.6.19\u002Fapp\u002FHooks\u002FHandlers\u002FSubmissionHandler.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-payment-form\u002F4.6.20\u002Fapp\u002FHooks\u002FHandlers\u002FSubmissionHandler.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-payment-form\u002F4.6.19\u002Fapp\u002FHooks\u002FHandlers\u002FSubmissionHandler.php\t2026-03-11 04:30:34.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-payment-form\u002F4.6.20\u002Fapp\u002FHooks\u002FHandlers\u002FSubmissionHandler.php\t2026-04-16 07:13:06.000000000 +0000\n@@ -40,17 +40,20 @@\n         if (!isset($_REQUEST['form_data'])) {\n             return;\n         }\n-\n+        if (!isset($_REQUEST['wpf_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['wpf_nonce'])), 'wpf_form_submission')) {\n+            wp_send_json_error(array(\n+                'message' => __('Security verification failed. Please refresh and try again.', 'wp-payment-form'),\n+            ), 403);\n+        }\n+\n         parse_str($_REQUEST['form_data'], $form_data);\n-        $form_localize = Arr::get($_REQUEST['form_localize'], 'conditional_logic');\n         \u002F\u002F Now Validate the form please\n         if(isset($_REQUEST['form_id'])){\n             $formId = absint(sanitize_text_field(wp_unslash($_REQUEST['form_id'])));\n         }\n         $this->formID = $formId;\n \n-        \u002F\u002F Get Original Form Elements Now\n-        $totalPayableAmount = intval(wp_unslash($_REQUEST['main_total'] ?? 0));\n         do_action('wppayform\u002Fform_submission_activity_start', $formId);\n \n         $form = Form::getForm($formId);\n@@ -60,13 +63,11 @@\n                 'message' => __('Invalid request. Please try again', 'wp-payment-form'),\n             ), 423);\n         }\n- \n         $formattedElements = Form::getFormattedElements($formId);\n \n         $numericCalculation = [];\n         $submittedNumericCalculation = apply_filters('wppayform\u002Fdynamic_payment_calculation', '', $numericCalculation, $formattedElements, $form_data);\n-\n-        $this->validate($form_data, $formattedElements, $form, $form_localize);\n+        $this->validate($form_data, $formattedElements, $form);\n \n         $paymentMethod = apply_filters('wppayform\u002Fchoose_payment_method_for_submission', '', $formattedElements['payment_method_element'], $formId, $form_data);","To exploit this vulnerability, an attacker targets the AJAX endpoint \u002Fwp-admin\u002Fadmin-ajax.php or the custom routing mechanism used by Paymattic. For unauthorized subscription cancellation, an unauthenticated attacker crafts a POST request to the custom router endpoint (often wppayform_api) specifying the target route 'dashboard\u002Fform\u002F{id}\u002Fentries\u002F{entryId}\u002Fcancel-subscription'. Because the plugin fails to verify that the requester owns the entry or has sufficient capabilities, providing a valid form ID and entry ID (which are often sequential and guessable) allows the attacker to cancel any active subscription. Similarly, the form submission handler (wpf_submit_form) can be exploited via CSRF or unauthorized unauthenticated requests due to the lack of nonce verification.","gemini-3-flash-preview","2026-05-04 18:02:35","2026-05-04 18:03:33",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","4.6.19","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-payment-form\u002Ftags\u002F4.6.19","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwp-payment-form.4.6.19.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-payment-form\u002Ftags\u002F4.6.20","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwp-payment-form.4.6.20.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-payment-form\u002Ftags"]