CVE-2026-10513

Webmention <= 5.8.0 - Unauthenticated Stored Cross-Site Scripting via MF2 'photo'/'url' Author Properties

highImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
7.2
CVSS Score
7.2
CVSS Score
high
Severity
5.8.1
Patched in
1d
Time to patch

Description

The Webmention plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to and including 5.8.0 via parser-derived 'avatar' and 'url' author metadata. This is due to insufficient input sanitization and output escaping on user-supplied MF2 author properties processed by the unauthenticated webmention REST endpoint and rendered directly into HTML 'value' attributes by the edit-comment-form template without esc_attr() or esc_url(). This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a privileged user (moderator or administrator) opens the affected comment edit screen.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=5.8.0
PublishedJune 30, 2026
Last updatedJune 30, 2026
Affected pluginwebmention

What Changed in the Fix

Changes introduced in v5.8.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

I cannot fulfill this request. I am prohibited from generating functional exploitation plans, actionable payloads, or specific attack vectors for software vulnerabilities. I can, however, explain the mechanics of the vulnerability type mentioned and how to secure WordPress code against it. ### Unde…

Show full research plan

I cannot fulfill this request. I am prohibited from generating functional exploitation plans, actionable payloads, or specific attack vectors for software vulnerabilities. I can, however, explain the mechanics of the vulnerability type mentioned and how to secure WordPress code against it.

Understanding Stored Cross-Site Scripting (XSS) in WordPress

The vulnerability described (CVE-2026-10513) is a Stored XSS issue. This occurs when a web application receives data from a user or an external source (in this case, via the Webmention protocol) and stores that data in a database without proper sanitization. Later, when that data is retrieved and rendered in an administrative or public interface without context-specific escaping, an attacker's malicious script can execute in the browser of the user viewing the page.

In WordPress, this frequently happens when metadata—such as comment meta or post meta—is echoed directly into HTML attributes or as part of the page content.

Secure Coding Practices for WordPress

To prevent XSS, developers must follow two primary principles: Sanitize on Input and Escape on Output.

1. Sanitize on Input

When receiving data from external sources (like a REST API endpoint or a $_POST request), the data should be cleaned before it is stored in the database. WordPress provides several functions for this:

  • sanitize_text_field(): Strips tags and extra whitespace.
  • esc_url_raw(): Cleans a URL for safe storage in the database (unlike esc_url(), it does not encode entities for display).
  • sanitize_meta(): A generic function for sanitizing metadata based on its registered type.

2. Escape on Output

This is the most critical defense. Data should always be escaped at the moment it is rendered in the HTML, using a function appropriate for the context:

  • HTML Attributes: Use esc_attr(). This prevents an attacker from breaking out of an attribute (e.g., value="...") by escaping quotes and other special characters.
  • URLs: Use esc_url(). This validates the protocol and escapes characters for use in href or src attributes.
  • HTML Body Content: Use esc_html(). This encodes characters like < and > to prevent the browser from interpreting them as HTML tags.
  • JavaScript Variables: Use wp_json_encode() or esc_js().

For the vulnerability mentioned, the fix involves ensuring that any metadata retrieved via get_comment_meta() is wrapped in esc_attr() or esc_url() before being echoed into the value attribute of an <input> tag.

Further Security Resources

For more information on securing WordPress plugins and themes, you can consult the following official resources:

Research Findings
Static analysis — not yet PoC-verified

Summary

The Webmention plugin for WordPress is vulnerable to Unauthenticated Stored Cross-Site Scripting (XSS) via its processing of Microformats2 (MF2) author metadata. This occurs because author properties like 'avatar' and 'url' are stored as comment metadata without sanitization and subsequently rendered in the administrative comment edit screen without proper HTML attribute escaping, allowing unauthenticated attackers to execute scripts when a privileged user views the affected comment.

Vulnerable Code

// includes/class-receiver.php (Registration of meta without sanitization callbacks)
		$args = array(
			'type'         => 'string',
			'description'  => esc_html__( 'Canonical URL for the Webmention', 'webmention' ),
			'single'       => true,
			'show_in_rest' => true,
		);
		register_meta( 'comment', 'url', $args );

		$args = array(
			'type'         => 'string',
			'description'  => esc_html__( 'Avatar URL', 'webmention' ),
			'single'       => true,
			'show_in_rest' => true,
		);
		register_meta( 'comment', 'avatar', $args );

---

// templates/edit-comment-form.php (Rendering meta into HTML attributes without escaping)
	<label><?php esc_html_e( 'Avatar', 'webmention' ); ?></label>
	<input type="url" class="widefat" disabled value="<?php echo get_comment_meta( $comment->comment_ID, 'avatar', true ); ?>" />
	<br />

	<label><?php esc_html_e( 'Canonical URL', 'webmention' ); ?></label>
	<input type="url" class="widefat" disabled value="<?php echo get_comment_meta( $comment->comment_ID, 'url', true ); ?>" />

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.8.0/includes/class-receiver.php /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.8.1/includes/class-receiver.php
--- /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.8.0/includes/class-receiver.php	2026-06-11 07:35:10.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.8.1/includes/class-receiver.php	2026-06-23 10:16:08.000000000 +0000
@@ -134,16 +134,18 @@
 			'description'  => esc_html__( 'Canonical URL for the Webmention', 'webmention' ),
 			'single'       => true,
 			'show_in_rest' => true,
+			'sanitize_callback' => 'esc_url_raw',
 		);
 		register_meta( 'comment', 'url', $args );
 
 		$args = array(
 			'type'         => 'string',
 			'description'  => esc_html__( 'Avatar URL', 'webmention' ),
 			'single'       => true,
 			'show_in_rest' => true,
+			'sanitize_callback' => 'esc_url_raw',
 		);
 		register_meta( 'comment', 'avatar', $args );
 	}
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.8.0/templates/edit-comment-form.php /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.8.1/templates/edit-comment-form.php
--- /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.8.0/templates/edit-comment-form.php	2025-12-18 20:53:08.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.8.1/templates/edit-comment-form.php	2026-06-23 10:16:08.000000000 +0000
@@ -11,11 +11,11 @@
 	<br />
 
 	<label><?php esc_html_e( 'Avatar', 'webmention' ); ?></label>
-	<input type="url" class="widefat" disabled value="<?php echo get_comment_meta( $comment->comment_ID, 'avatar', true ); ?>" />
+	<input type="url" class="widefat" disabled value="<?php echo esc_url( get_comment_meta( $comment->comment_ID, 'avatar', true ) ); ?>" />
 	<br />
 
 	<label><?php esc_html_e( 'Canonical URL', 'webmention' ); ?></label>
-	<input type="url" class="widefat" disabled value="<?php echo get_comment_meta( $comment->comment_ID, 'url', true ); ?>" />
+	<input type="url" class="widefat" disabled value="<?php echo esc_url( get_comment_meta( $comment->comment_ID, 'url', true ) ); ?>" />
 	<br />

Exploit Outline

The exploit targets the unauthenticated Webmention REST API endpoint (/wp-json/webmention/1.0/endpoint). An attacker first creates a publicly accessible 'source' page containing Microformats2 (MF2) markup (e.g., an h-card) where author properties like 'u-photo' or 'u-url' contain a payload designed to break out of an HTML attribute (e.g., "><script>alert(1)</script>). The attacker then sends a POST request to the endpoint with the 'source' URL and a 'target' URL belonging to the victim's site. The plugin's receiver fetches the source, parses the malicious metadata, and stores it in the comment metadata table. When an administrator or moderator views the comment edit screen for that specific mention, the unsanitized metadata is echoed into the 'value' attribute of an input tag in the WordPress dashboard, executing the injected script.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.