CVE-2025-68437 Overview
Craft CMS contains a Server-Side Request Forgery (SSRF) vulnerability in the GraphQL save_<VolumeName>_Asset mutation. The _file input accepts a url parameter that the server fetches without validating the destination host. Attackers with asset management GraphQL permissions can supply internal IP addresses or cloud metadata endpoints, forcing the backend to retrieve content from restricted services. The fetched content is stored as an asset and can be accessed and exfiltrated by the attacker.
The flaw affects Craft CMS versions 5.0.0-RC1 through 5.8.20 and 4.0.0-RC1 through 4.16.16. Patched releases 5.8.21 and 4.16.17 enforce hostname validation to block IP addresses and malformed hosts.
Critical Impact
Authenticated attackers can pivot through the Craft CMS backend to reach cloud metadata services (such as AWS IMDS at 169.254.169.254) and internal network resources, enabling credential theft and lateral movement.
Affected Products
- Craft CMS 5.0.0-RC1 through 5.8.20
- Craft CMS 4.0.0-RC1 through 4.16.16
- Deployments exposing the GraphQL endpoint with asset-upload permissions
Discovery Timeline
- 2026-01-05 - CVE-2025-68437 published to the National Vulnerability Database (NVD)
- 2026-09-30 - Last updated in NVD database
Technical Details for CVE-2025-68437
Vulnerability Analysis
The vulnerability resides in the GraphQL asset mutation resolver located at src/gql/resolvers/mutations/Asset.php. When a client submits a save_<VolumeName>_Asset mutation containing a _file input with a url field, the server retrieves the remote content and stores it as an asset within the targeted volume. The resolver does not restrict the destination host, so the request can target any address the application server can reach.
Successful exploitation requires an authenticated session with GraphQL permissions to manage assets in the targeted volume. The fetched response body is persisted as an asset file, and the attacker retrieves it through the standard asset access path. This turns the SSRF into a readable channel for internal HTTP responses, including cloud instance metadata and intranet services.
Root Cause
The root cause is missing hostname validation on attacker-controlled URLs passed through the _file.url input [CWE-918]. The resolver trusted parse_url output without checking whether the host resolved to a reserved range or whether it was a raw IP address. The patch inserts a filter requiring the hostname to pass FILTER_VALIDATE_DOMAIN with the FILTER_FLAG_HOSTNAME flag and rejects any value that FILTER_VALIDATE_IP recognizes.
Attack Vector
An attacker authenticates to the GraphQL endpoint with a token holding asset-save permissions. The attacker then issues a mutation whose _file.url points at an internal address such as http://169.254.169.254/latest/meta-data/iam/security-credentials/ or an unauthenticated intranet service. The server performs the HTTP request from its own network position and stores the response. The attacker downloads the resulting asset to recover the exfiltrated content.
} elseif (!empty($fileInformation['url'])) {
$url = $fileInformation['url'];
+ // make sure the hostname is alphanumeric and not an IP address
+ $hostname = parse_url($url, PHP_URL_HOST);
+ if (
+ !filter_var($hostname, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) ||
+ filter_var($hostname, FILTER_VALIDATE_IP)
+ ) {
+ throw new UserError("$url contains an invalid hostname.");
+ }
+
if (empty($fileInformation['filename'])) {
$filename = AssetsHelper::prepareAssetName(pathinfo(UrlHelper::stripQueryString($url), PATHINFO_BASENAME));
} else {
Source: Craft CMS commit 013db636. The patch rejects URLs whose hostname fails domain validation or parses as a literal IP address.
Detection Methods for CVE-2025-68437
Indicators of Compromise
- GraphQL requests containing save_ mutations with _file.url values pointing at RFC1918 ranges, loopback addresses, or 169.254.169.254
- Newly created assets whose source URL hostname is a raw IPv4 or IPv6 literal
- Outbound HTTP requests from the Craft CMS application server to cloud metadata endpoints that correlate with GraphQL activity
Detection Strategies
- Inspect web server logs for POST requests to the GraphQL endpoint containing the save_ asset mutation combined with a url input
- Query the Craft assets table for recently uploaded records whose stored source URL matches internal address patterns
- Correlate authenticated GraphQL tokens with anomalous outbound destinations originating from the application server
Monitoring Recommendations
- Alert when the Craft CMS host initiates connections to link-local, loopback, or private IP ranges that it does not normally contact
- Monitor GraphQL audit logs for asset mutations issued by accounts that do not routinely upload remote files
- Track IMDS (Instance Metadata Service) access attempts and require IMDSv2 session tokens on AWS workloads to blunt metadata theft
How to Mitigate CVE-2025-68437
Immediate Actions Required
- Upgrade Craft CMS to version 5.8.21 or 4.16.17 without delay
- Rotate any cloud credentials, API tokens, or secrets reachable from the Craft CMS instance in case metadata was retrieved
- Audit GraphQL schemas and tokens to confirm which accounts hold save permissions on asset volumes
Patch Information
Craft CMS addressed the issue in releases 5.8.21 and 4.16.17. Review the GitHub Security Advisory GHSA-x27p-wfqw-hfcc and the CraftCMS 5.8.21 Changelog for release notes. The fix lives in commit 013db636 and enforces hostname validation inside the asset mutation resolver.
Workarounds
- Revoke GraphQL asset-save permissions from untrusted tokens until the patch is applied
- Block egress from the Craft CMS application server to cloud metadata IPs (169.254.169.254, fd00:ec2::254) and internal management ranges
- Enforce IMDSv2 on AWS EC2 workloads to require session tokens that SSRF cannot easily acquire
# Restrict Craft CMS egress to cloud metadata and private ranges (iptables)
iptables -A OUTPUT -d 169.254.169.254 -m owner --uid-owner www-data -j REJECT
iptables -A OUTPUT -d 10.0.0.0/8 -m owner --uid-owner www-data -j REJECT
iptables -A OUTPUT -d 172.16.0.0/12 -m owner --uid-owner www-data -j REJECT
iptables -A OUTPUT -d 192.168.0.0/16 -m owner --uid-owner www-data -j REJECT
# Enforce IMDSv2 on AWS EC2 instance running Craft CMS
aws ec2 modify-instance-metadata-options \
--instance-id i-0123456789abcdef0 \
--http-tokens required \
--http-put-response-hop-limit 1
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.