Craft CMS CVE-2026-55791
MEDIUMAttack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
ReconIdentify Craft CMS behind shared cache
-
DeliverySend /actions/app/resource-js request with X-Forwarded-Host poisoning
-
ExploitYii2 rewrites $baseUrl, validation bypassed
-
InstallGuzzle fetches attacker JS, returned as application/javascript
-
C2Cache layer stores poisoned response for legitimate URI
-
ExecuteAdmin loads Control Panel, browser executes JS
-
ImpactSteal CSRF token, POST install-plugin for RCE
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A07:2025 - Authentication Failures
ASVS 5.0
V6 - Authentication Origin validation
|
| Exploitation Conditions | Requires three concrete conditions to reach maximum impact: (1) the target Craft 4.x/5.x instance must have assetManager.cacheSourcePaths set to false (the vulnerable Guzzle-fetch branch is gated on this); (2) trustedHosts must remain at its default value of ['any'], or include the attacker-controllable hostname, so Yii2 accepts X-Forwarded-Host header poisoning; (3) for the cache-poisoning → admin XSS → 1-click RCE chain, the site must sit behind a shared HTTP caching layer (Varnish/Fastly/Cloudflare/Nginx fastcgi_cache) AND an authenticated administrator must subsequently visit the Control Panel. Without condition (3) the impact is limited to blind SSRF and reflected JS to the requesting client only. The endpoint enforces requireCpRequest() but does not require authentication, so initial triggering is unauthenticated. |
| Impact | No CVSS vector or EPSS score was provided in the input, and the issue is not on the CISA KEV list - exploitation status is therefore 'no public exploit identified at time of analysis,' despite a fully documented vendor advisory describing the attack chain. The realistic ceiling is severe (unauthenticated RCE via web cache poisoning → admin XSS → plugin install session-riding), but the floor is much lower: it requires the non-default assetManager.cacheSourcePaths=false setting AND a shared HTTP cache layer in front of Craft AND an admin who subsequently logs in. Without the cache layer the impact degrades to blind SSRF and reflected JS to the triggering client only. The CWE-346 root cause and structural dependence on default trustedHosts='any' make this a real prioritization concern for any Craft 4.x/5.x deployment fronted by Varnish/Cloudflare/Fastly with non-default asset settings, but it is not a 'patch tonight' issue for default-config deployments. |
| Exploit ScenarioDerived | An unauthenticated attacker sends a request to /actions/app/resource-js with X-Forwarded-Host: attacker.tld and a url parameter pointing at attacker.tld; Yii2 trusts the header due to trustedHosts='any', $baseUrl is rewritten, the validation passes, and Guzzle (with redirects enabled) fetches attacker-controlled JavaScript and returns it with Content-Type: application/javascript. If the site sits behind a shared cache, the poisoned response is cached for the legitimate URI, so when an administrator next loads the Control Panel their browser executes the attacker's JS, which reads window.Craft.csrfTokenValue and POSTs to /admin/actions/plugins/install-plugin for RCE. The GitHub Security Advisory walks through these mechanics, but no standalone weaponized PoC has been published. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Jun 19, 2026
Server-Side Request Forgery and arbitrary JavaScript injection in Craft CMS 4.x (before 4.18) and 5.x (before 5.10) allow remote unauthenticated attackers to poison the Host or X-Forwarded-Host header against the /actions/app/resource-js endpoint, forcing the backend Guzzle client to proxy attacker-controlled content as application/javascript. When the instance sits behind a caching layer, this chains into web cache poisoning, stored XSS in the Control Panel, and 1-click RCE via session-riding the plugin install action. No public exploit identified at time of analysis, though the GitHub Security Advisory (GHSA-c55v-343g-5xff) provides detailed exploitation mechanics.
RemediationAI
Vendor-released patch: upgrade to Craft CMS 5.10 (5.x branch) or 4.18 (4.x branch), which remove actionResourceJs() entirely and instead load cross-domain script tags directly in the browser rather than via a server-side proxy (see PR https://github.com/craftcms/cms/pull/18559 and advisory https://github.com/craftcms/cms/security/advisories/GHSA-c55v-343g-5xff). If immediate upgrade is not possible, set assetManager.cacheSourcePaths to true so the vulnerable HTTP-fetch branch is never reached (trade-off: source paths must be recomputed/cached, which may impact initial CP load on large asset volumes), and explicitly set config/general.php $trustedHosts to your real public hostnames instead of relying on the default 'any' (trade-off: misconfiguration here can break legitimate URL generation behind load balancers). At the cache layer, vary or exclude /actions/app/resource-js from shared caches and strip incoming X-Forwarded-Host headers from untrusted clients.
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in composer
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
The flaw lives in craft\controllers\AppController::actionResourceJs() and is rooted in Yii2 trust-boundary handling (CWE-346, Origin Validation Error). Craft's default GeneralConfig::$trustedHosts is set to ['any'], which causes Yii2 to honor an attacker-supplied X-Forwarded-Host header and globally rewrite $baseUrl. The endpoint's str_starts_with($url, $baseUrl) check is then trivially satisfied because $baseUrl itself was poisoned, and Craft::createGuzzleClient()->get($url) fetches the resulting URL with ALLOW_REDIRECTS enabled before returning the body via asRaw() with a forced Content-Type: application/javascript header. CPE pkg:composer/craftcms_cms covers all 4.x and 5.x release branches up to the fixes. The vulnerability only manifests on instances where assetManager.cacheSourcePaths is set to false, which disables source-path caching and forces the HTTP fetch branch.
Know when Nginx gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N
Network-reachable and unauthenticated (AV:N/PR:N) but requires non-default cacheSourcePaths=false plus a shared cache and admin login (AC:H/UI:R); attacker JS executes in admin's browser crossing trust boundaries (S:C) enabling RCE.
Primary rating from Vendor (https://github.com/craftcms/cms).
CVSS VectorVendor: https://github.com/craftcms/cms
Lifecycle Timeline
1DescriptionCVE.org
1. Overview
Craft CMS is vulnerable to Server-Side Request Forgery (SSRF) and Arbitrary JavaScript Injection through the /actions/app/resource-js endpoint. By exploiting the default permissive trustedHosts configuration, an attacker can poison the Host or X-Forwarded-Host header to manipulate the application’s $baseUrl. This bypasses the endpoint’s internal URL validation, forcing the backend Guzzle client to fetch a malicious payload from an attacker-controlled server and reflect it to the client with a Content-Type: application/javascript header.
2. Vulnerability Mechanism (Root Cause) The vulnerability manifests when assetManager.cacheSourcePaths is set to false. The attack chain relies on three structural flaws and insecure defaults:
- A. Default Proxy Trust (
trustedHosts): Craft’s defaultGeneralConfig::$trustedHostsis set to['any']. This allows an attacker to bypass front-end web server (Nginx/Apache) strictHostheader validations by simply injecting anX-Forwarded-Hostheader. Yii2 will parse this and globally set$baseUrlto the attacker's domain. - B. Insecure HTTP Client (
actionResourceJs): InAppController::actionResourceJs(), thestr_starts_with($url, $baseUrl)validation is bypassed because$baseUrlis already poisoned by the attacker. The core then usesCraft::createGuzzleClient()->get($url). Unlike the GraphQL Asset fetcher, this Guzzle instance defaults toALLOW_REDIRECTS => true. - C. Forced JS Content-Type: The response fetched from the attacker's server is blindly returned to the user via
$this->asRaw()with the headerContent-Type: application/javascript.
3. Attack Scenario & Impact (Proof of Exploitability) This endpoint acts as a proxy, taking remote, unverified content and serving it as valid JavaScript. While the direct SSRF allows for internal network probing, the most devastating impact occurs when caching layers are involved.
If the Craft CMS instance is behind a caching layer, this vulnerability leads directly to Web Cache Poisoning:
- An unauthenticated attacker sends the poisoned request.
- The caching layer caches the malicious JavaScript response for the legitimate
/actions/app/resource-jsURI. - When an authenticated Administrator logs into the Control Panel, their browser loads the poisoned cached JavaScript (Stored XSS).
- The malicious script extracts
window.Craft.csrfTokenValueand silently sends a POST request to/admin/actions/plugins/install-plugin, achieving 1-Click Remote Code Execution (RCE) via Session Riding.
Articles & Coverage 1
Executive ViewAI
Craft CMS instances running versions 4.x and 5.x are exposed to a critical vulnerability that allows unauthenticated attackers to inject persistent malicious code into cached responses, compromising administrator credentials and enabling complete platform takeover. Organizations dependent on Craft for content or commerce operations face potential data breaches, operational shutdown, and regulatory exposure if unpatched.
Apply vendor patch.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Cross-Site Scripting occurs when an application accepts untrusted data and sends it to a web browser without proper validation or encoding.
Server-Side Request Forgery exploits applications that fetch remote resources based on user-supplied URLs.
Remote Code Execution represents the critical moment when an attacker successfully runs arbitrary code on a target system without physical access.
Affected Products (CPE)CVE.org
Denial of service against HTTP/2 server implementations allows remote unauthenticated attackers to exhaust server resour
The ngx_http_parse_chunked function in http/ngx_http_parse.c in nginx 1.3.9 through 1.4.0 allows remote attackers to cau
A critical vulnerability in Kubernetes ingress-nginx controller allows unauthenticated attackers with pod network access
nginx 0.8.41 through 1.4.3 and 1.5.x before 1.5.7 allows remote attackers to bypass intended restrictions via an unescap
An issue was discovered on GL.iNet devices before version 4.5.0. Rated critical severity (CVSS 9.8), this vulnerability
Nginx versions since 0.5.6 up to and including 1.13.2 are vulnerable to integer overflow vulnerability in nginx range fi
The resolver in nginx before 1.8.1 and 1.9.x before 1.9.10 allows remote attackers to cause a denial of service (invalid
Kubernetes ingress-nginx contains a configuration injection vulnerability via the mirror-target and mirror-host Ingress
A security issue was discovered in ingress-nginx https://github.com/kubernetes/ingress-nginx where the `auth-url` Ingres
A security issue was discovered in ingress-nginx https://github.com/kubernetes/ingress-nginx where the `auth-tls-match-c
Roxy-WI is a web interface for managing Haproxy, Nginx, Apache and Keepalived servers. Rated critical severity (CVSS 9.8
The STARTTLS implementation in mail/ngx_mail_smtp_handler.c in the SMTP proxy in nginx 1.5.x and 1.6.x before 1.6.1 and
GHSA-c55v-343g-5xff
NVD
CVE.org
EPSS
Exploit-DB