WP Manifestindependent plugin directory
manifest / ecommerce / wp-loyalty-optin

WPLoyalty - Opt-in WP Registry grade C-. High-severity findings · 1 findingWP RegistryHigh-severity findings · 1 findingOpen the reportC-

★ 0stars
204release downloads
≈90active sites
stablelatest · 11mo ago

Install

Download wp-loyalty-optin.zip From the stable release on GitHub, Nov 26, 2025

Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/wployalty/wp-loyalty-optin/releases/download/stable/wp-loyalty-optin.zip
Updates itself. It ships its own updater (Plugin Update Checker), so new versions appear under Dashboard → Updates.

Releases

2 releases. Each count is every asset in that release; expand a row for the breakdown.

Tag
Published
Assets
Downloads
stable latest
Nov 26, 2025 11mo ago
wp-loyalty-optin.zip
119
Jun 19, 2025 1 year ago
wp-loyalty-optin-v1.0.0.zip
85

Active-site estimate ≈90 comes from the median of recent superseded releases. Method.

C- grade

Security

WPLoyalty - Opt-in 1.0.0 · audited by WP Registry

High-severity findings.

1 high
Audited release
1.0.0
Findings
1
Worst severity
high
Content hash
80f42792913c2051fb4e2708…

Findings

  • high Guest checkout or extra email= overwrites any customer’s loyalty opt-in

    missing_auth

    Users::save() INSERT/UPDATEs {$wpdb->prefix}wlr_optin_users by user_email with no ownership check. Four unauthenticated (or customer) writers call updateUserOptInStatus() with an attacker-chosen email: (1) saveCheckoutFormData on woocommerce_checkout_create_order uses the order billing_email plus POST accept_wployalty_membership (unchecked box is absent → status 0). Guest checkout is enabled by default and WooCommerce does not stop a guest from using a registered customer’s email as billing_email. (2) checkBlockCheckoutEarning on woocommerce_store_api_checkout_update_customer_from_request reads $customer->get_billing_email() and extensions.wlopt_checkout_block.wlr_optin during Store API place-order (permission_callback __return_true, cart token only). (3) updateOrderFromRequest json_decodes the raw Store API body and uses billing_address.email. (4) registerUserHandler on user_register loads the new account email then immediately replaces it with Input::get('email') from $_REQUEST, so an extra email=victim@… field on wp-login registration or checkout create-account writes the victim’s row while the order/account stays on the attacker. Contrast: the shortcode AJAX correctly binds to get_login_user_email(). Observable: victim optin_status=0; preventWPLoyaltyMembership then hides loyalty UI and blocks earning/redemption for that email on subsequent requests.

    App/Controller/Site/Main.php:355-386,476-485,540-581

    Recommendation

    Bind opt-in writes to a proven identity: for logged-in users always use get_current_user_id() / account email (ignore billing_email and $_REQUEST['email']). For guests, INSERT a row for the order/session email only when no wp_users / wlr_optin_users row already exists for that address; never UPDATE another customer’s optin_status from checkout or registration. In registerUserHandler use get_userdata($user_id)->user_email and drop Input::get('email').

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.