Skip to content

Harden checkout OTP: prevent dev-tools bypass, timing-safe comparison, phone pinning#9

Open
Copilot wants to merge 5 commits intomainfrom
copilot/propose-plugin-architecture-otp
Open

Harden checkout OTP: prevent dev-tools bypass, timing-safe comparison, phone pinning#9
Copilot wants to merge 5 commits intomainfrom
copilot/propose-plugin-architecture-otp

Conversation

Copy link

Copilot AI commented Feb 26, 2026

The checkout OTP flow was bypassable via browser dev tools — a user could verify phone A then swap billing phone to B before placing the order. Additionally, several patterns would not pass WordPress plugin review (raw echo json_encode, timing-vulnerable === on OTP, missing SameSite cookie attribute).

Architecture change (from prior commits)

Checkout OTP rendering moved from woocommerce_review_order_before_submit (broken in block checkout / Elementor / custom themes) to a self-contained panel via wp_footer. Verification uses a session-flag pattern: AJAX verifies OTP → sets transient flag → server-side hooks check flag on checkout submission. Works with classic, block, and any page-builder checkout.

Security hardening

  • Phone pinningverified_phone_matches() compares the billing phone at order submission against the OTP-verified phone stored in the transient. Mismatch → order blocked, session cleared.
// Classic checkout
if ($this->checkout_phone_matches_verified()) { ... }

// Block checkout — uses order object directly
if ($this->verified_phone_matches($order->get_billing_phone())) { ... }
  • Timing-safe OTP comparisonauthenticate_otp() uses hash_equals() instead of ===

  • SameSite cookie — Session cookie now sets SameSite=Lax via PHP 7.3+ options array with positional-arg fallback

  • wp_send_json() — Replaced all echo wp_kses_post(json_encode(...)); wp_die(); exit; in send_otp_for_reg() and save_and_send_otp_login() with wp_send_json() (proper Content-Type, safe termination). Also fixed null object access when user lookup fails.

Nonce coverage (audit)

Endpoint Nonce
wc_send_otp (checkout) check_ajax_referer('alpha_sms_checkout_otp', ...)
wc_send_otp (WC/WP reg) wp_verify_nonce(..., 'wc_reg_phone_action') / wp_reg_phone_action
alpha_sms_verify_checkout_otp check_ajax_referer('alpha_sms_checkout_otp', ...)
save_and_send_otp_login check_ajax_referer('ajax-login-nonce', ...)
validate_guest_checkout_otp Server-side only (transient flag)
validate_block_checkout_otp Server-side only (transient flag + RouteException)

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits February 26, 2026 00:52
…X verification, block checkout support

Co-authored-by: md-riaz <33659227+md-riaz@users.noreply.github.com>
…omment

Co-authored-by: md-riaz <33659227+md-riaz@users.noreply.github.com>
Copilot AI changed the title [WIP] Propose architecture for WooCommerce guest OTP verification Refactor checkout OTP to theme-agnostic architecture with session-based verification Feb 26, 2026
Copilot AI and others added 2 commits February 26, 2026 02:40
…rison, SameSite cookie, wp_send_json

Co-authored-by: md-riaz <33659227+md-riaz@users.noreply.github.com>
…ite comment

Co-authored-by: md-riaz <33659227+md-riaz@users.noreply.github.com>
Copilot AI changed the title Refactor checkout OTP to theme-agnostic architecture with session-based verification Harden checkout OTP: prevent dev-tools bypass, timing-safe comparison, phone pinning Feb 26, 2026
@md-riaz md-riaz marked this pull request as ready for review February 26, 2026 03:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants