CVE-2026-32261
Description
Webhooks for Craft CMS plugin adds the ability to manage “webhooks” in Craft CMS, which will send GET or POST requests when certain events occur. From version 3.0.0 to before version 3.2.0, the Webhooks plugin renders user-supplied template content through Twig’s renderString() function without sandbox protection. This allows an authenticated user with access to the Craft control panel and permissions to access the Webhooks plugin to inject Twig template code that calls arbitrary PHP functions. This is possible even if allowAdminChanges is set to false. This issue has been patched in version 3.2.0.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
craftcms/webhooksPackagist | >= 3.0.0, < 3.2.0 | 3.2.0 |
Affected products
1Patches
188344991a68bUse the Twig sandbox
4 files changed · +808 −547
CHANGELOG.md+8 −0 modified@@ -1,5 +1,13 @@ # Release Notes for Webhooks for Craft CMS +## Unreleased + +> [!WARNING] +> Payload, header, webhook URL, and debounce key templates are now rendered in a sandboxed Twig environment, when `enableTwigSandbox` is enabled. + +- Webhooks now requires Craft 4.17+ or 5.9+. +- Fixed a [high-severity](https://github.com/craftcms/cms/security/policy#severity--remediation) RCE vulnerability. (GHSA-8wg7-wm29-2rvg) + ## 3.1.1 - 2025-07-29 - Fixed a PHP error that could occur if a webhook header was null. ([#97](https://github.com/craftcms/webhooks/issues/97))
composer.json+1 −1 modified@@ -27,7 +27,7 @@ "prefer-stable": true, "require": { "php": "^8.0.2", - "craftcms/cms": "^4.0.0-RC2|^5.0.0-beta.1" + "craftcms/cms": "^4.17.0|^5.9.0" }, "require-dev": { "craftcms/ecs": "dev-main",
composer.lock+795 −542 modifiedsrc/Plugin.php+4 −4 modified@@ -155,7 +155,7 @@ function(Event $e) use ($webhook) { if (in_array($webhook->method, ['post', 'put'], true)) { // Build out the body data if ($webhook->payloadTemplate) { - $json = $view->renderString($webhook->payloadTemplate, [ + $json = $view->renderSandboxedString($webhook->payloadTemplate, [ 'event' => $e, ]); $data = Json::decodeIfJson($json); @@ -188,7 +188,7 @@ function(Event $e) use ($webhook) { $header['value'] = App::parseEnv($header['value']); if (is_string($header['value'])) { - $header['value'] = $view->renderString($header['value'], [ + $header['value'] = $view->renderSandboxedString($header['value'], [ 'event' => $e, ]); } @@ -219,13 +219,13 @@ function(Event $e) use ($webhook) { // Queue the send request up $url = App::parseEnv($webhook->url); - $url = $view->renderString($url, [ + $url = $view->renderSandboxedString($url, [ 'event' => $e, ]); if ($webhook->debounceKeyFormat) { $debounceKey = App::parseEnv($webhook->debounceKeyFormat); - $debounceKey = $webhook->id . ':' . $view->renderString($debounceKey, [ + $debounceKey = $webhook->id . ':' . $view->renderSandboxedString($debounceKey, [ 'event' => $e, ]); }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4News mentions
7- Wordfence Intelligence Weekly WordPress Vulnerability Report (April 27, 2026 to May 3, 2026)Wordfence Blog · May 7, 2026
- Bridging the gap: How to integrate Claude Security into the Tenable One Exposure Management PlatformTenable Blog · Apr 30, 2026
- Wordfence Intelligence Weekly WordPress Vulnerability Report (April 20, 2026 to April 26, 2026)Wordfence Blog · Apr 30, 2026
- The Q1 vulnerability pulseCisco Talos Intelligence · Apr 16, 2026
- Artifacts: versioned storage that speaks GitCloudflare Blog · Apr 16, 2026
- The n8n n8mare: How threat actors are misusing AI workflow automationCisco Talos Intelligence · Apr 15, 2026
- How AI Assistants are Moving the Security GoalpostsKrebs on Security · Mar 8, 2026