Craft CMS has Stored XSS in Table Field via "HTML" Column Type
Description
Craft is a content management system (CMS). In versions 4.5.0-RC1 through 4.16.18 and 5.0.0-RC1 through 5.8.22, a stored Cross-site Scripting (XSS) vulnerability exists in the editableTable.twig component when using the html column type. The application fails to sanitize the input, allowing an attacker to execute arbitrary JavaScript when another user views a page with the malicious table field. In order to exploit the vulnerability, an attacker must have an administrator account, and allowAdminChanges must be enabled in production, which is against Craft's security recommendations. Versions 4.16.19 and 5.8.23 patch the issue.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Craft CMS table field stored XSS allows arbitrary JavaScript execution via unsanitized html column type, requiring admin privileges and allowAdminChanges enabled.
Vulnerability
Overview
CVE-2026-27126 is a stored Cross-Site Scripting (XSS) vulnerability in Craft CMS's editableTable.twig component when the html column type is used. The application fails to sanitize input for this column type, allowing an attacker to inject arbitrary JavaScript that executes when another user views a page containing the malicious table field [1]. The issue affects Craft CMS versions 4.5.0-RC1 through 4.16.18 and 5.0.0-RC1 through 5.8.22 [3].
Exploitation
Prerequisites and Method
Exploitation requires an attacker to have an administrator account, and allowAdminChanges must be enabled in production—a configuration against Craft's security recommendations [1]. The attack involves creating a table field with a Single-line text column, then intercepting the save request to change the column type to html and injecting a payload (e.g., ``) into the default values [3]. The payload is stored and executed when other users view the compromised page or when an administrator edits the field configuration [3].
Impact
Successful exploitation allows execution of arbitrary JavaScript in the context of any user visiting affected pages. This can lead to data exfiltration, session hijacking, or further compromise of the Craft CMS installation. The vulnerability is particularly significant because administrators might unintentionally create such fields, especially since the html column type is not available in the UI dropdown and must be injected via manipulated requests [2][3].
Mitigation
Craft CMS has released patches in versions 4.16.19 and 5.8.23 that validate column types against a whitelist, preventing the html type from being set outside the intended interface [2][3]. Additionally, disabling allowAdminChanges in production environments prevents exploitation, even on unpatched versions [1][3]. Users are strongly advised to update to the latest patched versions and adhere to security configuration best practices.
AI Insight generated on May 19, 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 |
|---|---|---|
craftcms/cmsPackagist | >= 4.5.0-RC1, < 4.16.19 | 4.16.19 |
craftcms/cmsPackagist | >= 5.0.0-RC1, < 5.8.23 | 5.8.23 |
Affected products
1Patches
1f5d488d9bb6eEnsure column types are within the supported range
1 file changed · +34 −27
src/fields/Table.php+34 −27 modified@@ -39,6 +39,8 @@ */ class Table extends Field { + private static array $typeOptions; + /** * @inheritdoc */ @@ -55,6 +57,31 @@ public static function valueType(): string return 'array|null'; } + private static function typeOptions(): array + { + if (!isset(self::$typeOptions)) { + self::$typeOptions = [ + 'checkbox' => Craft::t('app', 'Checkbox'), + 'color' => Craft::t('app', 'Color'), + 'date' => Craft::t('app', 'Date'), + 'select' => Craft::t('app', 'Dropdown'), + 'email' => Craft::t('app', 'Email'), + 'heading' => Craft::t('app', 'Row heading'), + 'lightswitch' => Craft::t('app', 'Lightswitch'), + 'multiline' => Craft::t('app', 'Multi-line text'), + 'number' => Craft::t('app', 'Number'), + 'singleline' => Craft::t('app', 'Single-line text'), + 'time' => Craft::t('app', 'Time'), + 'url' => Craft::t('app', 'URL'), + ]; + + // Make sure they are sorted alphabetically (post-translation) + asort(self::$typeOptions); + } + + return self::$typeOptions; + } + /** * @var bool Whether the rows should be static. * @since 4.5.0 @@ -149,14 +176,6 @@ public function __construct($config = []) } } } - // encode the default cell values for html-type cells - if ($col['type'] == 'html') { - foreach ($config['defaults'] as &$row) { - if (isset($row[$colId])) { - $row[$colId] = Html::encode($row[$colId]); - } - } - } } } @@ -198,7 +217,13 @@ protected function defineRules(): array */ public function validateColumns(): void { + $typeOptions = self::typeOptions(); + foreach ($this->columns as &$col) { + if (!isset($typeOptions[$col['type']])) { + $col['type'] = 'singleline'; + } + if ($col['handle']) { $error = null; @@ -252,24 +277,6 @@ public function getContentColumnType(): string */ public function getSettingsHtml(): ?string { - $typeOptions = [ - 'checkbox' => Craft::t('app', 'Checkbox'), - 'color' => Craft::t('app', 'Color'), - 'date' => Craft::t('app', 'Date'), - 'select' => Craft::t('app', 'Dropdown'), - 'email' => Craft::t('app', 'Email'), - 'heading' => Craft::t('app', 'Row heading'), - 'lightswitch' => Craft::t('app', 'Lightswitch'), - 'multiline' => Craft::t('app', 'Multi-line text'), - 'number' => Craft::t('app', 'Number'), - 'singleline' => Craft::t('app', 'Single-line text'), - 'time' => Craft::t('app', 'Time'), - 'url' => Craft::t('app', 'URL'), - ]; - - // Make sure they are sorted alphabetically (post-translation) - asort($typeOptions); - $columnSettings = [ 'heading' => [ 'heading' => Craft::t('app', 'Column Heading'), @@ -291,7 +298,7 @@ public function getSettingsHtml(): ?string 'heading' => Craft::t('app', 'Type'), 'class' => 'thin', 'type' => 'select', - 'options' => $typeOptions, + 'options' => self::typeOptions(), ], ];
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-3jh3-prx3-w6wcghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-27126ghsaADVISORY
- github.com/craftcms/cms/commit/f5d488d9bb6eff7670ed2c2fe30e15692e92c52bghsax_refsource_MISCWEB
- github.com/craftcms/cms/security/advisories/GHSA-3jh3-prx3-w6wcghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.