Potential Code Injection in Sprout Forms
Description
Server-Side Template Injection in Sprout Forms Notification Emails allows Twig code execution via custom fields.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Server-Side Template Injection in Sprout Forms Notification Emails allows Twig code execution via custom fields.
Vulnerability
Overview
CVE-2020-11056 is a Server-Side Template Injection (SSTI) vulnerability in Sprout Forms before version 3.9.0, specifically within the Notification Emails feature. The root cause lies in how the software constructs template paths for custom email templates. In affected versions, Sprout Forms concatenated the site path directly with the user-provided email template identifier, allowing an attacker to manipulate the path and inject Twig code that would be rendered server-side [1][2].
Exploitation
An attacker with the ability to create or modify custom fields in Sprout Forms Notification Emails can exploit this vulnerability. No authentication is required beyond standard administrative access to the form builder. The attacker injects malicious Twig syntax into custom field values; when a notification email is generated, the user-controlled input is rendered as a template, resulting in code execution. The patch (commit 5ef759f) refactors the template path handling to treat the templates folder as a base and uses a separate getTemplateRoot() method, preventing arbitrary path traversal and injection [2].
Impact
Successful exploitation allows an attacker to execute arbitrary Twig code on the server. Depending on the Twig environment's configuration, this can lead to full server compromise, including reading sensitive data, modifying site content, or leveraging the server for further attacks. The advisory credits Paweł Hałdrzyński and Daniel Kalinowski from ISEC.PL for discovering and responsibly disclosing this issue [4].
Mitigation
The vulnerability is fixed in Sprout Forms version 3.9.0, which also upgrades sprout-base-email to v1.2.7 [3][4]. Users who cannot upgrade immediately should work around the issue by using only the "Basic Notification (Sprout Email)" template and avoiding any custom templates that display form fields [4].
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
barrelstrength/sprout-base-emailPackagist | < 1.2.7 | 1.2.7 |
barrelstrength/sprout-formsPackagist | < 3.9.0 | 3.9.0 |
Affected products
3- ghsa-coords2 versions
< 1.2.7+ 1 more
- (no CPE)range: < 1.2.7
- (no CPE)range: < 3.9.0
- barrelstrength/Sprout Formsv5Range: < 3.9.0
Patches
15ef759f4713eRefactor Email Templates to treat /templates folder as base folder when rendering
4 files changed · +30 −10
src/base/EmailElement.php+2 −2 modified@@ -196,7 +196,7 @@ public function getEmailTemplates() $emailTemplates = new $settings->emailTemplateId(); } else { // custom folder on site path - $templatePath = $sitePath.DIRECTORY_SEPARATOR.$settings->emailTemplateId; + $templatePath = $settings->emailTemplateId; $emailTemplates = new CustomTemplates(); $emailTemplates->setPath($templatePath); @@ -222,7 +222,7 @@ public function getEmailTemplates() if ($isCustom) { // custom folder on site path - $templatePath = $sitePath.DIRECTORY_SEPARATOR.$emailTemplateId; + $templatePath = $emailTemplateId; $emailTemplates = new CustomTemplates(); $emailTemplates->setPath($templatePath);
src/base/EmailTemplates.php+16 −7 modified@@ -2,7 +2,9 @@ namespace barrelstrength\sproutbaseemail\base; +use barrelstrength\sproutbaseemail\emailtemplates\CustomTemplates; use Craft; +use craft\web\View; use League\HTMLToMarkdown\HtmlConverter; use Twig\Error\LoaderError; use Twig\Error\RuntimeError; @@ -37,9 +39,16 @@ abstract class EmailTemplates abstract public function getName(): string; /** - * The folder path where your email templates exist + * The root folder where the Email Templates exist * - * This value should be a folder. Sprout Email will look for a required email.html file and an optional email.txt file within this folder. + * @return string + */ + abstract public function getTemplateRoot(): string; + + /** + * The folder path where your email templates exist in relation to the folder defined in [[self::getTemplateRoot]] + * + * This value should also be a folder. Sprout Email will look for a required email.twig file and an optional email.txt file within this folder. * * @return string */ @@ -103,15 +112,15 @@ protected function processEmailTemplates() { $view = Craft::$app->getView(); $oldTemplatePath = $view->getTemplatesPath(); - $view->setTemplatesPath($this->getPath()); - // @todo - make dynamic - $htmlEmailTemplate = 'email.html'; - $textEmailTemplate = 'email.txt'; + $view->setTemplatesPath($this->getTemplateRoot()); + + $htmlEmailTemplate = null; + $textEmailTemplate = $this->getPath().'/email.txt'; // Allow other extensions for email.html foreach (Craft::$app->getConfig()->getGeneral()->defaultTemplateExtensions as $extension) { - $templateName = 'email.'.$extension; + $templateName = $this->getPath().'/email.'.$extension; if (Craft::$app->getView()->doesTemplateExist($templateName)) { $htmlEmailTemplate = $templateName;
src/emailtemplates/BasicTemplates.php+6 −1 modified@@ -18,12 +18,17 @@ public function getName(): string return Craft::t('sprout-base-email', 'Basic Notification (Sprout Email)'); } + public function getTemplateRoot(): string + { + return Craft::getAlias('@sproutbaseemail/templates'); + } + /** * @return string */ public function getPath(): string { - return Craft::getAlias('@sproutbaseemail/templates/_components/emailtemplates/basic'); + return '_components/emailtemplates/basic'; } }
src/emailtemplates/CustomTemplates.php+6 −0 modified@@ -4,6 +4,7 @@ use barrelstrength\sproutbaseemail\base\EmailTemplates; use Craft; +use craft\web\View; /** * The Custom Templates is used to dynamically create an EmailTemplate @@ -28,6 +29,11 @@ public function getName(): string return Craft::t('sprout-base-email', 'Custom Templates'); } + public function getTemplateRoot(): string + { + return Craft::$app->getView()->getTemplatesPath(); + } + /** * @return string */
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-px8v-hxxx-2rghghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2020-11056ghsaADVISORY
- github.com/barrelstrength/craft-sprout-base-email/commit/5ef759f4713ede6dbf77c9d9df9f992876e43a49ghsaWEB
- github.com/barrelstrength/craft-sprout-forms/blob/v3/CHANGELOG.mdghsax_refsource_MISCWEB
- github.com/barrelstrength/craft-sprout-forms/security/advisories/GHSA-px8v-hxxx-2rghghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.