CVE-2026-34897

Media Library Assistant <= 3.34 - Authenticated (Contributor+) Stored Cross-Site Scripting

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
3.35
Patched in
8d
Time to patch

Description

The Media Library Assistant plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 3.34 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.34
PublishedApril 6, 2026
Last updatedApril 13, 2026

What Changed in the Fix

Changes introduced in v3.35

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

mode=list`. *Which is more likely?* The description says "Stored XSS in pages". In WordPress, "pages" usually means frontend. So Shortcode is the winner. - Target: `[mla_gallery]`. - Attribute: `mla_markup`. - Payload: `inline:<script>alert('CVE-2026-34897')</script>`. …

Show full research plan

mode=list`.

*Which is more likely?*
The description says "Stored XSS in pages". In WordPress, "pages" usually means frontend.
So Shortcode is the winner.

- Target: `[mla_gallery]`.
- Attribute: `mla_markup`.
- Payload: `inline:<script>alert('CVE-2026-34897')</script>`.

*Wait!* Does `[mla_gallery]` require an attachment to render?
Usually, yes. So we should ensure at least one attachment exists.
`wp media import /path/to/image.jpg`

1.  Create a Contributor.
2.  Upload an image (to ensure the shortcode has something to process).
3.  Create a post with `[mla_gallery post_mime_type=all mla_markup="inline:<script>alert(document.domain)</script>"]`.
4.  Navigate to the post as Admin.
5.  Check for alert.

`MLACore::mla_get_option( MLACoreOptions::MLA_MEDIA_MODAL_TOOLBAR )`
If we wanted to exploit the Media Modal specifically. But shortcodes are easier to automate.

*Final check on Nonce Acquisition:*
Even if not strictly needed for the Shortcode, I will provide the steps to get `mla_admin_nonce` because the prompt asks for it.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Media Library Assistant plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the [mla_gallery] shortcode. This occurs because the 'mla_markup' attribute, specifically when using the 'inline:' prefix, does not sufficiently sanitize or escape user-provided HTML, allowing authenticated attackers with Contributor-level access and above to inject arbitrary scripts into pages.

Vulnerable Code

// includes/class-mla-data.php (Approx. line 150 in 3.34)
public static function mla_parse_template( $tpl, $markup_values ) {
	// If templates are present we must step through $tpl and expand them
	if ( isset( $markup_values['[+template_count+]'] ) ) {
		$offset = 0;
		while ( false !== $start = strpos( $tpl, '[+', $offset ) ) {
			if ( $template_content = self::_find_template_substring( substr( $tpl, $start ) ) ) {
				$template_length = strlen( $template_content );
				$template_content = substr( $template_content, 11, $template_length - (11 + 2) );
				$template_content = self::_expand_field_level_template( $template_content, $markup_values );

				$tpl = substr_replace( $tpl, $template_content, $start, $template_length );
				$offset = $start + strlen( $template_content );
			} else { // found template
				$offset = $start + 2;
			}
		} // while substitution parameter present
	} // templates are present

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/media-library-assistant/3.34/includes/class-mla-core.php /home/deploy/wp-safety.org/data/plugin-versions/media-library-assistant/3.35/includes/class-mla-core.php
--- /home/deploy/wp-safety.org/data/plugin-versions/media-library-assistant/3.34/includes/class-mla-core.php	2026-03-07 00:56:28.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/media-library-assistant/3.35/includes/class-mla-core.php	2026-03-30 00:02:10.000000000 +0000
@@ -21,7 +21,7 @@
 	 *
 	 * @var	string
 	 */
-	const CURRENT_MLA_VERSION = '3.34';
+	const CURRENT_MLA_VERSION = '3.35';
 
 	/**
 	 * Current date for Development Versions, empty for production versions
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/media-library-assistant/3.34/includes/class-mla-data.php /home/deploy/wp-safety.org/data/plugin-versions/media-library-assistant/3.35/includes/class-mla-data.php
--- /home/deploy/wp-safety.org/data/plugin-versions/media-library-assistant/3.34/includes/class-mla-data.php	2026-03-07 00:56:28.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/media-library-assistant/3.35/includes/class-mla-data.php	2026-03-19 22:37:14.000000000 +0000
@@ -4278,6 +4288,22 @@
 
 		$id3_metadata = self::mla_fetch_attachment_id3_metadata( $post_id );
 		if ( ! empty( $id3_metadata ) && !isset( $id3_metadata['error'] ) ) {
+			// Replace image blobs with a text message
+			if ( isset( $id3_metadata['comments']['picture'] ) && is_array( $id3_metadata['comments']['picture'] ) ) {
+				foreach ( $id3_metadata['comments']['picture'] as $key => $picture ) {
+					if ( isset( $picture['data'] ) ) {
+						$image_size = strlen( $picture['data'] );
+						$id3_metadata['comments']['picture'][ $key ]['data'] = '( ' . $image_size . ' ' . __( 'bytes of BINARY DATA', 'media-library-assistant' ) . ' )';
+					}
+				}
+
+			}
+
+			if ( isset( $id3_metadata['image']['data'] ) ) {
+				$image_size = strlen( $id3_metadata['image']['data'] );
+				$id3_metadata['image']['data'] = '( ' . $image_size . ' ' . __( 'bytes of BINARY DATA', 'media-library-assistant' ) . ' )';
+			}
+
 			$text .= self::_compose_metadata_array( $id3_metadata, 'id3', ':' );
 		}
 
... (truncated)

Exploit Outline

1. Login to the WordPress dashboard with a Contributor-level account or higher. 2. Create a new post or edit an existing one. 3. Add a shortcode block containing the [mla_gallery] shortcode. 4. Within the shortcode, add the 'mla_markup' attribute using the 'inline:' prefix to define a custom HTML template containing a script tag. Payload example: [mla_gallery post_mime_type=all mla_markup="inline:<script>alert(document.cookie)</script>"]. 5. Save or publish the post. 6. Navigate to the post's public URL (or preview it as an Administrator). The script provided in the 'mla_markup' attribute will execute in the browser context of the viewer.

Check if your site is affected.

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