--- a/aiktp/aiktp.php
+++ b/aiktp/aiktp.php
@@ -3,7 +3,7 @@
* Plugin Name: AIKTP
* Plugin URI: https://aiktp.com/wordpress
* Description: AIKTP - AI powered WordPress content automation. Create SEO optimized articles, bulk generate WooCommerce product descriptions, and sync posts directly from aiktp.com.
- * Version: 5.0.04
+ * Version: 5.0.5
* Author: John Luke - aiktp.com
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
@@ -21,7 +21,7 @@
}
// Define constants
-define('AIKTPZ_VERSION', '5.0.04');
+define('AIKTPZ_VERSION', '5.0.5');
define('AIKTPZ_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('AIKTPZ_PLUGIN_URL', plugin_dir_url(__FILE__));
// Include modules
--- a/aiktp/includes/aiktp-sync.php
+++ b/aiktp/includes/aiktp-sync.php
@@ -120,32 +120,30 @@
register_rest_route('aiktp', '/getToken', array(
'methods' => 'GET',
'callback' => array($this, 'get_valid_token'),
- 'permission_callback' => array($this, 'verify_user_logged_in')
+ 'permission_callback' => array($this, 'verify_admin_capability')
));
}
/**
- * Verify user is logged in (for token retrieval)
+ * Verify user has admin capability (for token retrieval)
*
- * This method ensures only logged-in users can retrieve the shared secret token.
- * SECURITY: Token retrieval must be restricted to authenticated users to prevent token leakage.
+ * This method ensures only administrators with manage_options capability can retrieve the shared secret token.
+ * SECURITY FIX (CVE-2026-1103): Previously only checked is_user_logged_in(), which allowed any authenticated
+ * user (including Subscribers) to retrieve the admin token. Now requires manage_options capability.
*
- * NOTE: We check get_current_user_id() directly because is_user_logged_in()
- * doesn't work reliably in REST API context without proper authentication headers.
+ * The token grants access to create posts, upload media, and access private content, so it must be
+ * restricted to administrators only.
*
* When calling this endpoint from JavaScript, you MUST include the nonce header:
* headers: { 'X-WP-Nonce': wpApiSettings.nonce }
*
* @param WP_REST_Request $request The REST API request object
- * @return bool|WP_Error True if user is logged in, WP_Error otherwise
+ * @return bool|WP_Error True if user has manage_options capability, WP_Error otherwise
*/
- public function verify_user_logged_in($request) {
- // Get current user ID - works better in REST API context
- $user_id = get_current_user_id();
-
- // If user ID is 0, user is not logged in
- if ($user_id === 0) {
+ public function verify_admin_capability($request) {
+ // Check if user is logged in first
+ if (!is_user_logged_in()) {
return new WP_Error(
'rest_forbidden',
__('You must be logged in to WordPress to access this endpoint. Please include authentication headers (X-WP-Nonce) in your request.', 'aiktp'),
@@ -153,6 +151,15 @@
);
}
+ // Check if user has manage_options capability (administrator)
+ if (!current_user_can('manage_options')) {
+ return new WP_Error(
+ 'rest_forbidden',
+ __('You do not have sufficient permissions to access this endpoint. Only administrators can retrieve the sync token.', 'aiktp'),
+ array('status' => 403)
+ );
+ }
+
return true;
}
@@ -228,19 +235,35 @@
// Verify the configured author exists and has edit_posts capability
$user = get_userdata($aiktp_author);
- if (!$user || !user_can($user, 'edit_posts')) {
- return new WP_Error(
- 'rest_forbidden',
- __('Configured AIKTP author does not have permission to create posts. Please check plugin settings.', 'aiktp'),
- array('status' => 403)
- );
+
+ // If configured author doesn't exist or doesn't have permissions, find a valid admin
+ if (!$user || !user_can($user, 'edit_posts') || !user_can($user, 'publish_posts')) {
+ // Try to find an administrator user
+ $admins = get_users(array(
+ 'role' => 'administrator',
+ 'number' => 1,
+ 'orderby' => 'ID',
+ 'order' => 'ASC'
+ ));
+
+ if (!empty($admins)) {
+ $user = $admins[0];
+ // Update the option to use this admin for future requests
+ update_option('aiktp_author', $user->ID);
+ } else {
+ return new WP_Error(
+ 'rest_forbidden',
+ __('No administrator user found. Please ensure at least one administrator account exists.', 'aiktp'),
+ array('status' => 403)
+ );
+ }
}
- // Also verify publish_posts capability for publish operations
- if (!user_can($user, 'publish_posts')) {
+ // Double-check the user has required capabilities
+ if (!user_can($user, 'edit_posts') || !user_can($user, 'publish_posts')) {
return new WP_Error(
'rest_forbidden',
- __('Configured AIKTP author does not have permission to publish posts. Please check plugin settings.', 'aiktp'),
+ __('User does not have permission to create and publish posts.', 'aiktp'),
array('status' => 403)
);
}
@@ -269,10 +292,34 @@
$aiktp_author = get_option('aiktp_author', 1);
$user = get_userdata($aiktp_author);
+ // If configured author doesn't exist or doesn't have upload permission, find a valid admin
if (!$user || !user_can($user, 'upload_files')) {
+ // Try to find an administrator user
+ $admins = get_users(array(
+ 'role' => 'administrator',
+ 'number' => 1,
+ 'orderby' => 'ID',
+ 'order' => 'ASC'
+ ));
+
+ if (!empty($admins)) {
+ $user = $admins[0];
+ // Update the option to use this admin for future requests
+ update_option('aiktp_author', $user->ID);
+ } else {
+ return new WP_Error(
+ 'rest_forbidden',
+ __('No administrator user found. Please ensure at least one administrator account exists.', 'aiktp'),
+ array('status' => 403)
+ );
+ }
+ }
+
+ // Double-check the user has upload capability
+ if (!user_can($user, 'upload_files')) {
return new WP_Error(
'rest_forbidden',
- __('Configured AIKTP author does not have permission to upload files. Please check plugin settings.', 'aiktp'),
+ __('User does not have permission to upload files.', 'aiktp'),
array('status' => 403)
);
}
@@ -328,8 +375,8 @@
* Get Valid Token
*
* SECURITY NOTE:
- * Authentication is handled by the permission_callback (verify_user_logged_in).
- * This function simply generates/returns the token for authenticated users.
+ * Authentication is handled by the permission_callback (verify_admin_capability).
+ * This function simply generates/returns the token for authenticated administrators.
*
* We do NOT manually validate cookies or set current user here.
* WordPress REST API handles authentication automatically.