Craft has a SSRF in GraphQL Asset Mutation via Alternative IP Notation
Description
Craft is a platform for creating digital experiences. In Craft versions 4.0.0-RC1 through 4.16.17 and 5.0.0-RC1 through 5.8.21, the saveAsset GraphQL mutation uses filter_var(..., FILTER_VALIDATE_IP) to block a specific list of IP addresses. However, alternative IP notations (hexadecimal, mixed) are not recognized by this function, allowing attackers to bypass the blocklist and access cloud metadata services. This issue is patched in versions 4.16.18 and 5.8.22.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Craft CMS SSRF via GraphQL saveAsset mutation bypasses IP blocklist using alternative IP notations (hexadecimal, mixed).
Vulnerability
Details
Craft CMS versions 4.0.0-RC1 through 4.16.17 and 5.0.0-RC1 through 5.8.21 contain an SSRF vulnerability in the saveAsset GraphQL mutation [1][4]. The mutation uses PHP's filter_var($hostname, FILTER_VALIDATE_IP) to block specific IP addresses (e.g., cloud metadata IP 169.254.169.254). However, this function only recognizes standard dotted-decimal IP notation; alternative representations such as hexadecimal (0xa9fea9fe) or mixed decimal-hex (169.254.0xa9fe) are not flagged as IPs, allowing them to pass validation [3][4]. When the URL is later resolved by GuzzleHTTP, it correctly interprets these alternative notations as the original blocked IP, enabling the SSRF [4].
Exploitation
An attacker with the ability to send GraphQL mutations can craft a URL using alternative IP notation (e.g., http://169.254.0xa9fe/ or http://0xa9fea9fe/) and supply it as the _file.url argument to save_images_Asset [4]. No authentication is required beyond standard GraphQL access. The mutation then fetches content from the resolved IP, which is a cloud metadata service (e.g., AWS, GCP, Azure instance metadata) [1][4]. The proof of concept provided in the advisory demonstrates that Guzzle resolves these notations to the true IP 169.254.169.254 [4].
Impact
Successful exploitation allows an attacker to retrieve sensitive cloud metadata, including IAM credentials, configuration secrets, and other instance information. This can lead to lateral movement, privilege escalation, or data exfiltration within the cloud environment [1][4].
Mitigation
The issue is patched in Craft CMS versions 4.16.18 and 5.8.22 [1][2]. The fix, visible in commit d49e93e5ba0c48939ce5eaa6cd9b4a990542d8b2, converts hexadecimal hostname segments to decimal before validation [3]. Administrators should upgrade to the patched versions immediately. No workaround is recommended as the blocklist bypass defeats the intended protection [4].
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 | >= 5.0.0-RC1, < 5.8.22 | 5.8.22 |
craftcms/cmsPackagist | >= 4.0.0-RC1, < 4.16.18 | 4.16.18 |
Affected products
1Patches
1d49e93e5ba0cConvert hex hostname segments to decimals
2 files changed · +15 −2
CHANGELOG.md+1 −1 modified@@ -5,7 +5,7 @@ - The `utils/fix-field-layout-uids` command now checks for duplicate top-level field layout UUIDs. ([#18193](https://github.com/craftcms/cms/pull/18193)) - Fixed a bug where all plugin settings were being saved to the project config, rather than just posted settings. ([craftcms/commerce#4006](https://github.com/craftcms/commerce/issues/4006)) - Fixed a bug where custom selects could be positioned incorrectly after the window was resized. ([#18179](https://github.com/craftcms/cms/issues/18179)) -- Fixed an SSRF vulnerability. (GHSA-96pq-hxpw-rgh8) +- Fixed SSRF vulnerabilities. (GHSA-96pq-hxpw-rgh8, GHSA-m5r2-8p9x-hp5m) - Fixed a SQL injection vulnerability. (GHSA-2453-mppf-46cj) ## 4.16.17 - 2025-12-0421
src/gql/resolvers/mutations/Asset.php+14 −1 modified@@ -24,6 +24,7 @@ use GraphQL\Error\UserError; use GraphQL\Type\Definition\ResolveInfo; use GuzzleHttp\Client; +use Illuminate\Support\Collection; use Throwable; use yii\base\Exception; use yii\base\InvalidArgumentException; @@ -280,8 +281,20 @@ protected function handleUpload(AssetElement $asset, array $fileInformation): bo private function validateHostname(string $url): bool { - // make sure the hostname is alphanumeric and not an IP address $hostname = parse_url($url, PHP_URL_HOST); + + // convert hex segments to decimal + $hostname = Collection::make(explode('.', $hostname)) + ->map(function(string $chunk) { + if (str_starts_with($chunk, '0x')) { + $octets = str_split(substr($chunk, 2), 2); + return implode('.', array_map('hexdec', $octets)); + } + return $chunk; + }) + ->join('.'); + + // make sure the hostname is alphanumeric and not an IP address if ( !filter_var($hostname, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) || filter_var($hostname, FILTER_VALIDATE_IP)
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-m5r2-8p9x-hp5mghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-25494ghsaADVISORY
- github.com/craftcms/cms/commit/d49e93e5ba0c48939ce5eaa6cd9b4a990542d8b2ghsax_refsource_MISCWEB
- github.com/craftcms/cms/releases/tag/4.16.18ghsaWEB
- github.com/craftcms/cms/releases/tag/5.8.22ghsax_refsource_MISCWEB
- github.com/craftcms/cms/security/advisories/GHSA-m5r2-8p9x-hp5mghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.