CVE-2026-42649

Favicon Rotator <= 1.2.11 - Unauthenticated Stored Cross-Site Scripting

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

Description

The Favicon Rotator plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.2.11 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers 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: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<=1.2.11
PublishedApril 29, 2026
Last updatedMay 4, 2026
Affected pluginfavicon-rotator

What Changed in the Fix

Changes introduced in v1.2.12

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

* Plan must be precise. * Quote real function names. * Use `http_request` tool. * `FaviconRotator` class properties: * `prefix` = `fvrt` * `opt_key` = `options` -> prefixed to `fvrt_options` * `action_save` = `action_save` -> prefixed to `fvrt_…

Show full research plan
*   Plan must be precise.
*   Quote real function names.
*   Use `http_request` tool.

*   `FaviconRotator` class properties:
    *   `prefix` = `fvrt`
    *   `opt_key` = `options` -> prefixed to `fvrt_options`
    *   `action_save` = `action_save` -> prefixed to `fvrt_action_save`
    *   `opt_icons` = `icons`
*   Logic for `normalize_icons` in `model.php`.
*   Logic for `display_icons` hook `wp_head`.
*   In `class.media.php`, the method `register_type` creates a `type_name`. For 'favicon', it's `fvrt_favicon`.
*   Wait, `normalize_icons` uses `this->icon_type_default` which is `favicon`.

So the POST data is likely:
`fvrt_icons[favicon][0]=PAYLOAD`
and
`fvrt_action_save=1`

*   Check for `fvrt_options` using `wp option get fvrt_options`.
*   Check homepage using `http_request`.

*   If `fvrt_icons` doesn't work, maybe `fvrt_options[icons][favicon][0]`.
*   Or maybe just `icons
Research Findings
Static analysis — not yet PoC-verified

Summary

The Favicon Rotator plugin for WordPress is vulnerable to Unauthenticated Stored Cross-Site Scripting due to a lack of authorization checks and insufficient input sanitization in its settings save logic. This allows unauthenticated attackers to overwrite the plugin's icon settings with malicious JavaScript, which is then executed when any user (including administrators) visits the site's front-end or admin dashboard.

Vulnerable Code

// includes/class.media.php - Line 283 (approx)
// The plugin builds a JavaScript object by manually concatenating strings from an object 
// derived from POST data without using proper JSON encoding or escaping.
$arg_string = array();
foreach ( (array)$args as $key => $val ) {
    $arg_string[] = "'$key':'$val'";
}
$arg_string = '{' . implode(',', $arg_string) . '}';
?>
<script type="text/javascript">
/* <![CDATA[ */
var win = window.dialogArguments || opener || parent || top;
win.fvrt.media.setIcon(<?php echo $arg_string; ?>);
/* ]]> */
</script>

---

// includes/class.utilities.php - Line 465 (approx)
// The array_map function returns a new array and does not modify the input by reference.
// The escaped values are discarded, and the raw values are used in the attribute string.
function build_attribute_string($attr) {
    $ret = '';
    if ( is_object($attr) ) {
        $attr = (array) $attr;
    }
    if ( is_array($attr) ) {
        array_map('esc_attr', $attr); // Result is not assigned back to $attr
        $attr_str = array();
        foreach ( $attr as $key => $val ) {
            $attr_str[] = $key . '="' . $val . '"'; // $val remains unsanitized
        }
        $ret = implode(' ', $attr_str);
    }
    return $ret;
}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/favicon-rotator/1.2.11/includes/class.media.php /home/deploy/wp-safety.org/data/plugin-versions/favicon-rotator/1.2.12/includes/class.media.php
--- /home/deploy/wp-safety.org/data/plugin-versions/favicon-rotator/1.2.11/includes/class.media.php	2024-03-27 22:28:48.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/favicon-rotator/1.2.12/includes/class.media.php	2026-04-25 02:50:48.000000000 +0000
@@ -263,7 +268,7 @@
 			/* Send image data to main post edit form and close popup */
 			//Get Attachment ID
 			$args = new stdClass();
-			$args->id = esc_attr( $this->util->array_key_first( $_POST[ $this->var_setmedia ] ) );
+			$args->id = sanitize_key( $this->util->array_key_first( $_POST[ $this->var_setmedia ] ) );
 			//Make sure post is valid
 			if ( wp_attachment_is_image($args->id) ) {
 				$p = $this->get_request_props();
@@ -280,26 +285,25 @@
 				}
 			}
 			
-			//Build JS Arguments string
-			$arg_string = array();
-			foreach ( (array)$args as $key => $val ) {
-				$arg_string[] = "'$key':'$val'";
-			}
-			$arg_string = '{' . implode(',', $arg_string) . '}';
+			// Build JS output.
+			ob_start();
 			?>
-			<script type="text/javascript">
-			/* <![CDATA[ */
-			var win = window.dialogArguments || opener || parent || top;
-			win.fvrt.media.setIcon(<?php echo $arg_string; ?>);
-			/* ]]> */
+			<script>
+			( function() {
+				var win = window.dialogArguments || opener || parent || top;
+				win.fvrt.media.setIcon( <?php echo wp_json_encode( $args, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES | JSON_FORCE_OBJECT ) ?> );
+			}() );
 			</script>
 			<?php
+			// Output inline JS.
+			wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) );
 			exit;

Exploit Outline

1. The attacker targets a WordPress site with the Favicon Rotator plugin installed (version <= 1.2.11). 2. The attacker crafts a POST request to any WordPress endpoint (such as the homepage) that triggers the plugin's `init` or `admin_init` logic. 3. The request includes the parameters `fvrt_action_save=1` and `fvrt_icons[favicon][0]=<script>alert(1)</script>`. 4. Because the plugin lacks `current_user_can()` checks or nonce verification during the settings save process, it accepts the unauthenticated request and updates the `fvrt_options` WordPress option with the provided payload. 5. When any user visits the site, the plugin executes its `display_icons` function (hooked to `wp_head`), which retrieves the malicious string and outputs it directly into the `<head>` section of the page without escaping, leading to script execution.

Check if your site is affected.

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