Atomic Edge analysis of CVE-2026-4257:
This vulnerability is an unauthenticated Server-Side Template Injection (SSTI) leading to Remote Code Execution (RCE) in the Contact Form by Supsystic WordPress plugin versions <= 1.7.36. The plugin's prefill functionality allows attackers to inject arbitrary Twig expressions into form field values via GET parameters. The Twig template engine lacks sandboxing, enabling execution of arbitrary PHP functions and OS commands on the server. This critical vulnerability has a CVSS score of 9.8.
Atomic Edge research identifies the root cause in two components. The `cfsPreFill` function in `/classes/field.php` processes GET parameters to prefill form fields without proper sanitization. This function passes user-controlled input directly to the Twig template engine. The plugin uses the deprecated `Twig_Loader_String` class, which loads templates from strings rather than files. This combination allows unauthenticated users to inject Twig expressions that the engine evaluates. The vulnerability manifests because the Twig environment lacks a sandbox mode and does not restrict dangerous functions.
Exploitation occurs via HTTP GET requests to any page containing a vulnerable contact form. Attackers append GET parameters with field names prefixed by `cfs_`. For example, `?cfs_field_name={{malicious_twig}}`. The payload leverages Twig's `registerUndefinedFilterCallback()` method to register arbitrary PHP callbacks. A typical exploit chain uses `{{_self.env.registerUndefinedFilterCallback("system")}}` followed by `{{_self.env.getFilter("id")}}` to execute OS commands. Atomic Edge analysis confirms that no authentication is required, and the attack works from the frontend.
The patch in version 1.8.0 addresses the vulnerability by implementing input validation and escaping. The `cfsPreFill` function now applies `esc_attr()` to all prefilled values before passing them to the template engine. This HTML escaping neutralizes Twig expression delimiters like `{{` and `}}`. The diff shows changes in `/classes/field.php` where `$value = esc_attr($value);` is added within the prefill logic. The patch also updates the Twig library files to a newer version, but the primary fix is the escaping of user input before template rendering.
Successful exploitation grants attackers remote code execution with the web server's privileges. This typically means the ability to execute arbitrary PHP code and system commands. Attackers can read, modify, or delete files on the server, create backdoors, access databases, and pivot to internal networks. The vulnerability affects all WordPress sites running the vulnerable plugin version, requiring no user interaction or authentication. Atomic Edge assesses the impact as complete server compromise.
Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/contact-form-by-supsystic/cfs.php
+++ b/contact-form-by-supsystic/cfs.php
@@ -1,8 +1,9 @@
<?php
+
/**
* Plugin Name: Contact Form by Supsystic
* Description: Contact Form Builder with drag-and-drop editor to create responsive, mobile ready contact forms in a second. Custom fields and contact form templates
- * Version: 1.7.36
+ * Version: 1.8.0
* Author: supsystic.com
* Author URI: https://supsystic.com
* Text Domain: contact-form-by-supsystic
@@ -11,41 +12,41 @@
/**
* Base config constants and functions
*/
-require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . "config.php";
-require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . "functions.php";
+require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'config.php';
+require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'functions.php';
/**
* Connect all required core classes
*/
importSqlParser();
-importClassCfs("dbCfs");
-importClassCfs("installerCfs");
-importClassCfs("baseObjectCfs");
-importClassCfs("moduleCfs");
-importClassCfs("moduleWidgetCfs");
-importClassCfs("modelCfs");
-importClassCfs("modelSubscribeCfs");
-importClassCfs("viewCfs");
-importClassCfs("controllerCfs");
-importClassCfs("helperCfs");
-importClassCfs("dispatcherCfs");
-importClassCfs("fieldCfs");
-importClassCfs("tableCfs");
-importClassCfs("frameCfs");
+importClassCfs('dbCfs');
+importClassCfs('installerCfs');
+importClassCfs('baseObjectCfs');
+importClassCfs('moduleCfs');
+importClassCfs('moduleWidgetCfs');
+importClassCfs('modelCfs');
+importClassCfs('modelSubscribeCfs');
+importClassCfs('viewCfs');
+importClassCfs('controllerCfs');
+importClassCfs('helperCfs');
+importClassCfs('dispatcherCfs');
+importClassCfs('fieldCfs');
+importClassCfs('tableCfs');
+importClassCfs('frameCfs');
/**
* @deprecated since version 1.0.1
*/
-importClassCfs("langCfs");
-importClassCfs("reqCfs");
-importClassCfs("uriCfs");
-importClassCfs("htmlCfs");
-importClassCfs("responseCfs");
-importClassCfs("fieldAdapterCfs");
-importClassCfs("validatorCfs");
-importClassCfs("errorsCfs");
-importClassCfs("utilsCfs");
-importClassCfs("modInstallerCfs");
-importClassCfs("installerDbUpdaterCfs");
-importClassCfs("dateCfs");
+importClassCfs('langCfs');
+importClassCfs('reqCfs');
+importClassCfs('uriCfs');
+importClassCfs('htmlCfs');
+importClassCfs('responseCfs');
+importClassCfs('fieldAdapterCfs');
+importClassCfs('validatorCfs');
+importClassCfs('errorsCfs');
+importClassCfs('utilsCfs');
+importClassCfs('modInstallerCfs');
+importClassCfs('installerDbUpdaterCfs');
+importClassCfs('dateCfs');
/**
* Check plugin version - maybe we need to update database, and check global errors in request
*/
--- a/contact-form-by-supsystic/classes/Twig/Autoloader.php
+++ b/contact-form-by-supsystic/classes/Twig/Autoloader.php
@@ -16,33 +16,33 @@
*/
class Twig_Autoloader
{
- /**
- * Registers Twig_Autoloader as an SPL autoloader.
- *
- * @param bool $prepend Whether to prepend the autoloader or not.
- */
- public static function register($prepend = false)
- {
- if (version_compare(phpversion(), '5.3.0', '>=')) {
- spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
- } else {
- spl_autoload_register(array(__CLASS__, 'autoload'));
- }
+ /**
+ * Registers Twig_Autoloader as an SPL autoloader.
+ *
+ * @param bool $prepend Whether to prepend the autoloader or not.
+ */
+ public static function register($prepend = false)
+ {
+ if (version_compare(phpversion(), '5.3.0', '>=')) {
+ spl_autoload_register([__CLASS__, 'autoload'], true, $prepend);
+ } else {
+ spl_autoload_register([__CLASS__, 'autoload']);
}
+ }
- /**
- * Handles autoloading of classes.
- *
- * @param string $class A class name.
- */
- public static function autoload($class)
- {
- if (0 !== strpos($class, 'Twig')) {
- return;
- }
+ /**
+ * Handles autoloading of classes.
+ *
+ * @param string $class A class name.
+ */
+ public static function autoload($class)
+ {
+ if (0 !== strpos($class, 'Twig')) {
+ return;
+ }
- if (is_file($file = dirname(__FILE__).'/../'.str_replace(array('_', "