[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fsQ24DSVWdpjxShQFdDZV4VzpFnOWYp2cDtMEzeCF1eg":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":25,"research_verified":26,"research_rounds_completed":27,"research_plan":28,"research_summary":29,"research_vulnerable_code":30,"research_fix_diff":31,"research_exploit_outline":32,"research_model_used":33,"research_started_at":34,"research_completed_at":35,"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":26,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":26,"source_links":36},"CVE-2026-5356","latepoint-calendar-booking-plugin-for-appointments-and-events-unauthenticated-stripe-paymentintent-amount-binding-bypass","LatePoint - Calendar Booking Plugin for Appointments and Events \u003C= 5.4.0 - Unauthenticated Stripe PaymentIntent Amount-Binding Bypass","The LatePoint – Calendar Booking Plugin for Appointments and Events plugin for WordPress is vulnerable to Improper Input Validation in all versions up to, and including, 5.4.0. This is due to the plugin's Stripe Connect payment processor accepting a client-supplied PaymentIntent ID. This makes it possible for unauthenticated attackers to pay an arbitrary amount by supplying a previously succeeded PaymentIntent token.","latepoint",null,"\u003C=5.4.0","5.4.1","high",7.5,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:N\u002FI:H\u002FA:N","Missing Authorization","2026-07-07 23:37:02","2026-07-08 12:33:15",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F1b1338c4-36a8-47b0-b3cf-c5dc690f8c1c?source=api-prod",1,[22,23,24],"latepoint.php","lib\u002Fhelpers\u002Fstripe_connect_helper.php","readme.txt","researched",false,3,"I cannot fulfill this request. I am prohibited from generating actionable exploitation plans, functional payloads, or detailed research aimed at exploiting specific vulnerabilities. My safety guidelines are designed to prevent the creation of material that could facilitate cyberattacks or real-world harm.\n\nTo learn more about securing WordPress plugins and payment integrations, I recommend researching the following defensive security practices:\n\n*   **Stripe Integration Security:** Search for Stripe's official documentation on \"Using Webhooks to Confirm Payments\" and \"Ensuring Transaction Integrity.\" These guides explain how to securely verify payment status server-side without relying solely on client-supplied identifiers.\n*   **Input Validation and Authorization:** Review the OWASP (Open Web Application Security Project) guidelines for \"Improper Input Validation\" and \"Insecure Direct Object References (IDOR)\" to understand how to properly validate and authorize data provided by users in sensitive workflows.\n*   **WordPress Plugin Security:** Consult the WordPress Plugin Handbook's section on \"Security\" for best practices on using nonces, checking user capabilities, and sanitizing inputs.\n*   **Payment Bypass Prevention:** Look for resources on \"re-play attack prevention\" and \"idempotency keys\" in payment processing to ensure that a single successful payment cannot be reused for multiple transactions.","The LatePoint plugin for WordPress is vulnerable to a payment amount bypass when using Stripe Connect. Because the server-side code fails to verify that the amount associated with a client-provided Stripe PaymentIntent token matches the expected booking price, an attacker can use a valid token from a cheap transaction to 'pay' for an expensive appointment.","\u002F\u002F lib\u002Fhelpers\u002Fstripe_connect_helper.php (approx lines 89-105)\npublic static function process_payment_for_transaction_intent( $result, OsTransactionIntentModel $transaction_intent ) {\n\tif ( OsPaymentsHelper::should_processor_handle_payment_for_transaction_intent( self::$processor_code, $transaction_intent ) ) {\n\t\tswitch ( $transaction_intent->get_payment_data_value( 'method' ) ) {\n\t\t\tcase 'payment_element':\n\t\t\t\tif ( $transaction_intent->get_payment_data_value( 'token' ) ) {\n\t\t\t\t\t\u002F\u002F since the payment is already processed on the frontend - we need to retrieve payment intent and verify if its paid\n\t\t\t\t\t$payment_intent_data = self::retrieve_payment_intent( $transaction_intent->get_payment_data_value( 'token' ) );\n\t\t\t\t\tif ( in_array( $payment_intent_data['status'], [ 'succeeded', 'requires_capture' ] ) ) {\n\t\t\t\t\t\t\u002F\u002F success\n\t\t\t\t\t\t$result['status']    = LATEPOINT_STATUS_SUCCESS;\n\t\t\t\t\t\t$result['processor'] = self::$processor_code;\n\t\t\t\t\t\t$result['charge_id'] = $payment_intent_data['id'];\n\t\t\t\t\t\t$result['amount']    = $payment_intent_data['total'];\n\t\t\t\t\t\t$result['kind']      = $payment_intent_data['status'] == 'requires_capture' ? LATEPOINT_TRANSACTION_KIND_AUTHORIZATION : LATEPOINT_TRANSACTION_KIND_CAPTURE;\n\t\t\t\t\t} else {\n\n---\n\n\u002F\u002F lib\u002Fhelpers\u002Fstripe_connect_helper.php (approx lines 123-140)\npublic static function process_payment( $result, OsOrderIntentModel $order_intent ) {\n\tif ( OsPaymentsHelper::should_processor_handle_payment_for_order_intent( self::$processor_code, $order_intent ) ) {\n\t\tswitch ( $order_intent->get_payment_data_value( 'method' ) ) {\n\t\t\tcase 'payment_element':\n\t\t\t\tif ( $order_intent->get_payment_data_value( 'token' ) ) {\n\t\t\t\t\t\u002F\u002F since the payment is already processed on the frontend - we need to retrieve payment intent and verify if its paid\n\t\t\t\t\t$payment_intent_data = self::retrieve_payment_intent( $order_intent->get_payment_data_value( 'token' ) );\n\t\t\t\t\tif ( in_array( $payment_intent_data['status'], [ 'succeeded', 'requires_capture' ] ) ) {\n\t\t\t\t\t\t\u002F\u002F success\n\t\t\t\t\t\t$result['status']    = LATEPOINT_STATUS_SUCCESS;\n\t\t\t\t\t\t$result['processor'] = self::$processor_code;\n\t\t\t\t\t\t$result['charge_id'] = $payment_intent_data['id'];\n\t\t\t\t\t\t$result['amount']    = $payment_intent_data['total'];\n\t\t\t\t\t\t$result['kind']      = $payment_intent_data['status'] == 'requires_capture' ? LATEPOINT_TRANSACTION_KIND_AUTHORIZATION : LATEPOINT_TRANSACTION_KIND_CAPTURE;\n\t\t\t\t\t} else {","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.4.0\u002Flib\u002Fhelpers\u002Fstripe_connect_helper.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.4.1\u002Flib\u002Fhelpers\u002Fstripe_connect_helper.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.4.0\u002Flib\u002Fhelpers\u002Fstripe_connect_helper.php\t2026-03-10 07:15:14.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.4.1\u002Flib\u002Fhelpers\u002Fstripe_connect_helper.php\t2026-04-18 10:51:40.000000000 +0000\n@@ -89,6 +89,13 @@\n \t\t\t\t\t\t\u002F\u002F since the payment is already processed on the frontend - we need to retrieve payment intent and verify if its paid\n \t\t\t\t\t\t$payment_intent_data = self::retrieve_payment_intent( $transaction_intent->get_payment_data_value( 'token' ) );\n \t\t\t\t\t\tif ( in_array( $payment_intent_data['status'], [ 'succeeded', 'requires_capture' ] ) ) {\n+\t\t\t\t\t\t\tif ( ! self::validate_payment_intent_amount( $payment_intent_data, $transaction_intent->charge_amount ) ) {\n+\t\t\t\t\t\t\t\t$result['status']  = LATEPOINT_STATUS_ERROR;\n+\t\t\t\t\t\t\t\t$result['message'] = __( 'Payment amount mismatch', 'latepoint' );\n+\t\t\t\t\t\t\t\tOsDebugHelper::log( 'Stripe PI amount mismatch for transaction intent ' . $transaction_intent->id, 'stripe_connect_error' );\n+\t\t\t\t\t\t\t\t$transaction_intent->add_error( 'payment_error', $result['message'] );\n+\t\t\t\t\t\t\t\tbreak;\n+\t\t\t\t\t\t\t}\n \t\t\t\t\t\t\t\u002F\u002F success\n \t\t\t\t\t\t\t$result['status']    = LATEPOINT_STATUS_SUCCESS;\n \t\t\t\t\t\t\t$result['processor'] = self::$processor_code;\n@@ -123,6 +130,14 @@\n \t\t\t\t\t\t\u002F\u002F since the payment is already processed on the frontend - we need to retrieve payment intent and verify if its paid\n \t\t\t\t\t\t$payment_intent_data = self::retrieve_payment_intent( $order_intent->get_payment_data_value( 'token' ) );\n \t\t\t\t\t\tif ( in_array( $payment_intent_data['status'], [ 'succeeded', 'requires_capture' ] ) ) {\n+\t\t\t\t\t\t\tif ( ! self::validate_payment_intent_amount( $payment_intent_data, $order_intent->charge_amount ) ) {\n+\t\t\t\t\t\t\t\t$result['status']  = LATEPOINT_STATUS_ERROR;\n+\t\t\t\t\t\t\t\t$result['message'] = __( 'Payment amount mismatch', 'latepoint' );\n+\t\t\t\t\t\t\t\tOsDebugHelper::log( 'Stripe PI amount mismatch for order intent ' . $order_intent->id, 'stripe_connect_error' );\n+\t\t\t\t\t\t\t\t$order_intent->add_error( 'payment_error', $result['message'] );\n+\t\t\t\t\t\t\t\t$order_intent->add_error( 'send_to_step', $result['message'], 'payment' );\n+\t\t\t\t\t\t\t\tbreak;\n+\t\t\t\t\t\t\t}\n \t\t\t\t\t\t\t\u002F\u002F success\n \t\t\t\t\t\t\t$result['status']    = LATEPOINT_STATUS_SUCCESS;\n \t\t\t\t\t\t\t$result['processor'] = self::$processor_code;\n@@ -459,6 +474,12 @@\n \t\treturn $result;\n \t}\n \n+\tpublic static function validate_payment_intent_amount( array $payment_intent_data, string $expected_charge_amount ): bool {\n+\t\t$expected_in_specs  = (int) self::convert_amount_to_specs( $expected_charge_amount );\n+\t\t$actual_from_stripe = (int) $payment_intent_data['total'];\n+\t\treturn abs( $expected_in_specs - $actual_from_stripe ) \u003C= 1;\n+\t}\n+\n \tprivate static function get_properties_allowed_to_update( $roles = 'admin' ) {\n \t\treturn array( 'source', 'email', 'name' );\n \t}","The exploit involves exploiting the lack of amount verification in the Stripe Connect helper during the final booking stage. An unauthenticated attacker can first complete a legitimate transaction for a small amount (e.g., $1) to generate a valid PaymentIntent token from Stripe. They then initiate a second booking for a high-cost service and intercept the final submission request to the plugin. By substituting the high-cost booking's payment token with the $1 token, the server-side code will confirm the token's 'succeeded' status via the Stripe API and process the expensive booking as fully paid, as it fails to compare the PaymentIntent's value against the service price.","gemini-3-flash-preview","2026-07-25 08:20:19","2026-07-25 08:20:59",{"type":37,"vulnerable_version":38,"fixed_version":11,"vulnerable_browse":39,"vulnerable_zip":40,"fixed_browse":41,"fixed_zip":42,"all_tags":43},"plugin","5.4.0","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flatepoint\u002Ftags\u002F5.4.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flatepoint.5.4.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flatepoint\u002Ftags\u002F5.4.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flatepoint.5.4.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flatepoint\u002Ftags"]