Unauthenticated Privilege Escalation Vulnerability Patched in Kirki WordPress Plugin

On May 4th, 2026, we received a submission for an Unauthenticated Privilege Escalation vulnerability in the Kirki WordPress plugin. Although the plugin has more than 500,000 active installations, we estimate that only around 150,000 sites are using a vulnerable version, as the issue was introduced in the 6.0 major release. This vulnerability makes it possible for unauthenticated attackers to take over arbitrary user accounts on the site, including administrator accounts, by leveraging the plugin’s password reset functionality to have the password reset link delivered to an attacker-controlled email address.

Props to CHOIGYEONGMIN who discovered and responsibly reported this vulnerability through the Wordfence Bug Bounty Program. This researcher earned a bounty of $6,436 for this discovery. Our mission is to secure WordPress through defense in depth, which is why we are investing in quality vulnerability research and collaborating with researchers of this caliber through our Bug Bounty Program. We are committed to making the WordPress ecosystem more secure through the detection and prevention of vulnerabilities, which is a critical element to the multi-layered approach to security.

Wordfence Premium, Wordfence Care, and Wordfence Response users received a firewall rule to protect against any exploits targeting this vulnerability on May 9, 2026. Sites using the free version of Wordfence will receive the same protection 30 days later on June 8, 2026.

We provided full disclosure details to the Themeum team through our Wordfence Vulnerability Management Portal on May 15, 2026. The developer acknowledged the report on May 16, 2026, and released the fully patched version on May 18, 2026. We would like to commend the Themeum team for their prompt response and timely patch.

We urge users to update their sites to the latest patched version of Kirki, version 6.0.7 at the time of this publication, as soon as possible.

Vulnerability Summary from Wordfence Intelligence

CVSS Rating
9.8 (Critical)
Affected Version(s)
6.0.0 – 6.0.6
Patched Version
6.0.7
Bounty
$6,436.00
The Kirki – Freeform Page Builder, Website Builder & Customizer plugin for WordPress is vulnerable to privilege escalation via account takeover in all versions 6.0.0 to 6.0.6. This is due to the plugin accepting an arbitrary email address when a username is used in the password reset request. This makes it possible for unauthenticated attackers to send a password reset link for any user registered on the site to their own email address.

Technical Analysis

Kirki is a plugin that provides freeform page building, website building, and WordPress Customizer enhancements. As part of its frontend account management features, the plugin exposes a custom REST API endpoint that handles password reset requests.

Examining the code reveals that the plugin uses the handle_forgot_password() function in the CompLibFormHandler class to process the forgot password request. The function accepts both a username and an email parameter from the request body.

public function handle_forgot_password( $request ) {
	$form_data     = $request->get_body_params();
	$transiet_name = $this->validate_nonce( 'kirki-forgot-password' );
	$email    = isset( $form_data['email'] ) ? sanitize_email( $form_data['email'] ) : '';
	$username = isset( $form_data['username'] ) ? sanitize_text_field( $form_data['username'] ) : '';
	if ( strlen( $username ) === 0 && isset( $form_data['email'] ) && strlen( $email ) > 0 ) {
		$user = get_user_by( 'email', $email );
		if ( $user ) {
			$username = $user->get( 'user_login' );
		} else {
			$response = array(
				'message' => 'User not found',
			);
			return new WP_REST_Response( $response, 404 );
		}
	}
	if ( isset( $username ) && strlen( $username ) > 0 ) {
		$user = get_user_by( 'login', $username );
		if ( ! $user ) {
			$response = array(
				'message' => 'User not found',
			);
			return new WP_REST_Response( $response, 404 );
		}
		$key = get_password_reset_key( $user );
		if ( is_wp_error( $key ) ) {
			$response = array(
				'message' => $key->get_error_message(),
			);
			return new WP_REST_Response( $response, 500 );
		}
		// Prepare email content.
		$url = HelperFunctions::get_utility_page_url( 'reset_password' );
		$username  = $user->user_login;
		$chip_data = array(
			'username'    => $username,
			'email'       => $email,
			'displayname' => $user->display_name,
			'sitename'    => get_bloginfo( 'name' ),
			'reset_link'  => "$url?action=rp&key=$key&login=" . rawurlencode( $username ),
		);
		$email_subject = isset( $form_data['emailSubject'] ) ? sanitize_text_field( $form_data['emailSubject'] ) : '';
		$email_body    = '';
		if ( isset( $form_data['emailBody'] ) ) {
			$email_body = json_decode( $form_data['emailBody'], true );
			foreach ( $email_body as $key => $body_data ) {
				if ( isset( $body_data['type'] ) && isset( $body_data['value'] ) && $body_data['type'] === 'text' ) {
					$email_body = $email_body . $body_data['value'];
				} elseif ( isset( $body_data['type'] ) && isset( $body_data['value'] ) && $body_data['type'] === 'chip' ) {
					$email_body = $email_body . $chip_data[ $body_data['value'] ];
				}
			}
		}
		$email_body = nl2br( $email_body );
		$headers = array( 'Content-Type: text/html; charset=UTF-8' );
		// Send custom email.
		apply_filters( 'kirki_element_smtp', '' );
		$sent = wp_mail( $email, $email_subject, $email_body, $headers );
		if ( $sent ) {
			$response = array(
				'message' => 'Email sent',
			);
			delete_transient( $transiet_name );
			return new WP_REST_Response( $response, 200 );
		} else {
			$response = array(
				'message' => 'Failed to send email',
			);
			return new WP_REST_Response( $response, 500 );
		}
	}
	$response = array(
		'message' => 'Invalid request',
	);
	return new WP_REST_Response( $response, 400 );
}

The intended flow is that a user submits either their username or email, the plugin identifies the matching user account, generates a password reset key with get_password_reset_key(), and emails the reset link to that user.

Unfortunately, the function contains a critical logic flaw. When a username is provided, the plugin correctly retrieves the targeted user account. However, instead of using the email address associated with that account, it continues to use the email address supplied in the request. As a result, an attacker can specify an arbitrary email address even after the target account has been identified by username.

This means an unauthenticated attacker can send a request specifying a high-privileged username together with an attacker-controlled email address and receive a valid password reset link for the targeted account. Using the reset link, the attacker can set a new password and gain full control of the account.

As with all privilege escalation vulnerabilities, this can lead to complete site compromise through account takeover of administrator accounts, allowing the attacker to install malicious plugins, create new administrator users, modify site content, or deploy webshells for persistent access.

Wordfence Firewall

The following graphic demonstrates the steps to exploitation an attacker might take and at which point the Wordfence firewall would block an attacker from successfully exploiting the vulnerability.

Disclosure Timeline

May 4, 2026 – We received the submission for the Unauthenticated Privilege Escalation vulnerability in Kirki via the Wordfence Bug Bounty Program.
May 8, 2026 – We validated the report and confirmed the proof-of-concept exploit.
May 9, 2026Wordfence Premium, Care, and Response users received a firewall rule to provide added protection against any exploits that may target this vulnerability.
May 15, 2026 – The full disclosure details are sent instantly to the vendor upon verifying ownership of their software through our Wordfence Vulnerability Management Portal.
May 16, 2026 – The vendor acknowledged the report and began working on a fix.
May 18, 2026 – The fully patched version of the plugin, 6.0.7, was released.
June 8, 2026 – Wordfence Free users will receive the same protection.

Conclusion

In this blog post, we detailed an Unauthenticated Privilege Escalation vulnerability within the Kirki plugin affecting versions 6.0.0 through 6.0.6. This vulnerability allows unauthenticated attackers to take over user accounts, including administrator accounts, by exploiting the plugin’s password reset process so that the reset link is sent to an email address they control. The vulnerability has been fully addressed in version 6.0.7 of the plugin.

We encourage WordPress users to verify that their sites are updated to the latest patched version of Kirki as soon as possible considering the critical nature of this vulnerability.

Wordfence Premium, Wordfence Care, and Wordfence Response users received a firewall rule to protect against any exploits targeting this vulnerability on May 9, 2026. Sites using the free version of Wordfence will receive the same protection 30 days later on June 8, 2026.

If you know someone who uses this plugin on their site, we recommend sharing this advisory with them to ensure their site remains secure, as this vulnerability poses a significant risk.

The post Unauthenticated Privilege Escalation Vulnerability Patched in Kirki WordPress Plugin appeared first on Wordfence.

Leave a Comment