Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
cve-2026-9618-Patch — Hardened PHP replacement handlers for PeachPay Stripe capture and void AJAX endpoints, adding nonce verification, capability checks, and strict order and amount validation. | Kitploit
Tools/GitHubGitHub/sleepthegod/cve-2026-9618-patch
Authentication & AuthorizationDefensive ToolsStatic Code Analysis (SAST)Vulnerability AnalysisCode AnalysisWeb Security
GitHubsleepthegod/cve-2026-9618-patch

cve-2026-9618-Patch

Hardened PHP replacement handlers for PeachPay Stripe capture and void AJAX endpoints, adding nonce verification, capability checks, and strict order and amount validation.

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
View Repository
15 days agoNot yet reviewed

<?php
/**
 * Hardened PeachPay Stripe payment capture and void AJAX handlers.
 * By Taylor Christian Newsome
 * Security controls
 * - Authenticated AJAX requests only.
 * - Nonce verification.
 * - Strict order ID and amount validation.
 * - Order-specific authorization.
 * - Positive finite capture amounts.
 * - Exception handling and server-side logging.
 *
 * Requires WordPress, WooCommerce, and the PeachPay Stripe integration.
 */

defined( 'ABSPATH' ) || exit;

/**
 * Send a standardized JSON error and terminate execution.
 *
 * @param string $message Error message.
 * @param int    $status  HTTP response status.
 * @return void
 */
function peachpay_stripe_ajax_error( $message, $status = 400 ) {
	wp_send_json_error(
		array( 'message' => $message ),
		$status
	);
}

/**
 * Verify an AJAX nonce.
 *
 * @param string $action Nonce action.
 * @return void
 */
function peachpay_stripe_verify_ajax_nonce( $action ) {
	if (
		! isset( $_POST['security'] ) ||
		! is_string( $_POST['security'] )
	) {
		peachpay_stripe_ajax_error(
			'Invalid security token. Refresh the page and try again.',
			403
		);
	}

	$nonce = sanitize_text_field(
		wp_unslash( $_POST['security'] )
	);

	if ( ! wp_verify_nonce( $nonce, $action ) ) {
		peachpay_stripe_ajax_error(
			'Invalid security token. Refresh the page and try again.',
			403
		);
	}
}

/**
 * Validate and retrieve a positive order ID from POST data.
 *
 * @return int
 */
function peachpay_stripe_get_validated_order_id() {
	if (
		! isset( $_POST['order_id'] ) ||
		! is_string( $_POST['order_id'] ) &&
		! is_int( $_POST['order_id'] )
	) {
		peachpay_stripe_ajax_error(
			'A valid order_id is required.',
			400
		);
	}

	$raw_order_id = (string) wp_unslash( $_POST['order_id'] );

	// Reject arrays, decimals, signs, whitespace, and other malformed IDs.
	if (
		'' === $raw_order_id ||
		! ctype_digit( $raw_order_id ) ||
		(int) $raw_order_id < 1
	) {
		peachpay_stripe_ajax_error(
			'Invalid order_id.',
			400
		);
	}

	$order_id = absint( $raw_order_id );

	if ( $order_id < 1 ) {
		peachpay_stripe_ajax_error(
			'Invalid order_id.',
			400
		);
	}

	return $order_id;
}

/**
 * Retrieve an order and verify the current user is authorized to manage it.
 *
 * WooCommerce capability mappings can vary by version and configuration.
 * Confirm that these capabilities match the permissions used by your store.
 *
 * @param int $order_id Order ID.
 * @return WC_Order
 */
function peachpay_stripe_get_authorized_order( $order_id ) {
	if ( ! function_exists( 'wc_get_order' ) ) {
		peachpay_stripe_ajax_error(
			'WooCommerce is unavailable.',
			500
		);
	}

	$order = wc_get_order( $order_id );

	if ( ! $order ) {
		peachpay_stripe_ajax_error(
			'Order not found.',
			404
		);
	}

	if (
		! current_user_can( 'edit_shop_orders' ) ||
		! current_user_can( 'edit_shop_order', $order_id )
	) {
		peachpay_stripe_ajax_error(
			'Unauthorized to manage this order.',
			403
		);
	}

	return $order;
}

/**
 * Validate a positive decimal capture amount.
 *
 * This validates the syntax and numeric range. It does not establish the
 * Stripe payment intent's remaining capturable balance.
 *
 * @return float
 */
function peachpay_stripe_get_validated_capture_amount() {
	if (
		! isset( $_POST['amount_to_capture'] ) ||
		! is_string( $_POST['amount_to_capture'] ) &&
		! is_int( $_POST['amount_to_capture'] ) &&
		! is_float( $_POST['amount_to_capture'] )
	) {
		peachpay_stripe_ajax_error(
			'A valid amount_to_capture is required.',
			400
		);
	}

	$raw_amount = trim(
		(string) wp_unslash( $_POST['amount_to_capture'] )
	);

	// Accept ordinary decimal notation only; reject exponent notation,
	// signs, commas, currency symbols, and non-numeric input.
	if (
		'' === $raw_amount ||
		! preg_match( '/^\d+(?:\.\d+)?$/D', $raw_amount )
	) {
		peachpay_stripe_ajax_error(
			'Invalid amount to capture.',
			400
		);
	}

	// Reject excessively long values before converting to a float.
	if ( strlen( $raw_amount ) > 32 ) {
		peachpay_stripe_ajax_error(
			'Invalid amount to capture.',
			400
		);
	}

	$amount = (float) $raw_amount;

	if ( ! is_finite( $amount ) || $amount <= 0 ) {
		peachpay_stripe_ajax_error(
			'Invalid amount to capture.',
			400
		);
	}

	return $amount;
}

/**
 * Log a Stripe operation failure without exposing internal details to clients.
 *
 * @param string          $operation Operation name.
 * @param int             $order_id  Order ID.
 * @param Throwable       $exception Exception thrown.
 * @return void
 */
function peachpay_stripe_log_ajax_failure(
	$operation,
	$order_id,
	$exception
) {
	if ( function_exists( 'wc_get_logger' ) ) {
		wc_get_logger()->error(
			sprintf(
				'Stripe %s failed for order %d. Exception type: %s.',
				$operation,
				(int) $order_id,
				get_class( $exception )
			),
			array(
				'source' => 'peachpay-stripe',
			)
		);
	}
}

/**
 * Handle an authenticated AJAX request to capture a Stripe payment.
 *
 * @return void
 */
function peachpay_stripe_handle_capture_payment() {
	// 1. Verify request authenticity.
	peachpay_stripe_verify_ajax_nonce(
		'peachpay-stripe-capture-payment'
	);

	// 2. Validate the order ID and load an authorized order.
	$order_id = peachpay_stripe_get_validated_order_id();

	$order = peachpay_stripe_get_authorized_order(
		$order_id
	);

	// 3. Validate the requested capture amount.
	$raw_amount = peachpay_stripe_get_validated_capture_amount();

	// 4. Confirm the required PeachPay integration is available.
	if (
		! class_exists( 'PeachPay_Stripe' ) ||
		! is_callable( array( 'PeachPay_Stripe', 'format_amount' ) ) ||
		! is_callable( array( 'PeachPay_Stripe', 'capture_payment' ) )
	) {
		peachpay_stripe_ajax_error(
			'The Stripe payment integration is unavailable.',
			500
		);
	}

	try {
		// 5. Format the amount according to PeachPay's currency conventions.
		$amount_to_capture = PeachPay_Stripe::format_amount(
			$raw_amount,
			$order->get_currency()
		);

		if (
			! is_numeric( $amount_to_capture ) ||
			! is_finite( (float) $amount_to_capture ) ||
			(float) $amount_to_capture <= 0
		) {
			peachpay_stripe_ajax_error(
				'Invalid capture amount.',
				400
			);
		}

		/*
		 * IMPORTANT:
		 * capture_payment() must independently verify the Stripe PaymentIntent
		 * is capturable, enforce the remaining capturable balance, use the
		 * correct currency units, and handle duplicate requests safely.
		 */
		$result = PeachPay_Stripe::capture_payment(
			$order,
			$amount_to_capture
		);
	} catch ( Throwable $exception ) {
		peachpay_stripe_log_ajax_failure(
			'capture',
			$order_id,
			$exception
		);

		peachpay_stripe_ajax_error(
			'Unable to capture the payment. Please check the payment status.',
			500
		);
	}

	// Preserve the existing PeachPay response format.
	wp_send_json( $result );
}

/**
 * Handle an authenticated AJAX request to void a Stripe payment.
 *
 * @return void
 */
function peachpay_stripe_handle_void_payment() {
	// 1. Verify request authenticity.
	peachpay_stripe_verify_ajax_nonce(
		'peachpay-stripe-void-payment'
	);

	// 2. Validate the order ID and load an authorized order.
	$order_id = peachpay_stripe_get_validated_order_id();

	$order = peachpay_stripe_get_authorized_order(
		$order_id
	);

	// 3. Confirm the required PeachPay integration is available.
	if (
		! class_exists( 'PeachPay_Stripe' ) ||
		! is_callable( array( 'PeachPay_Stripe', 'void_payment' ) )
	) {
		peachpay_stripe_ajax_error(
			'The Stripe payment integration is unavailable.',
			500
		);
	}

	try {
		/*
		 * IMPORTANT:
		 * void_payment() must confirm the Stripe PaymentIntent is in a
		 * cancelable state. A payment that has already been captured cannot
		 * generally be voided; it may require a refund instead.
		 */
		$result = PeachPay_Stripe::void_payment( $order );
	} catch ( Throwable $exception ) {
		peachpay_stripe_log_ajax_failure(
			'void',
			$order_id,
			$exception
		);
Download Tool