CVE-2026-25497 Overview
CVE-2026-25497 is a Privilege Escalation vulnerability affecting Craft CMS, a platform for creating digital experiences. The flaw exists in Craft CMS's GraphQL API and allows an authenticated user with write access to one asset volume to escalate their privileges and modify or transfer assets belonging to any other volume, including restricted or private volumes to which they should not have access.
The saveAsset GraphQL mutation validates authorization against the schema-resolved volume but fetches the target asset by ID without verifying that the asset belongs to the authorized volume. This authorization bypass enables unauthorized cross-volume asset modification and transfer, potentially compromising sensitive digital assets across an organization's entire Craft CMS deployment.
Critical Impact
Authenticated attackers can bypass volume-level access controls to modify or transfer assets from restricted and private volumes, leading to unauthorized data access, data manipulation, and potential data exfiltration.
Affected Products
- Craft CMS versions 4.0.0-RC1 to before 4.17.0-beta.1
- Craft CMS versions 5.0.0 to before 5.9.0-beta.1
- Craft CMS version 5.8.22 and earlier (stable releases)
Discovery Timeline
- 2026-02-09 - CVE-2026-25497 published to NVD
- 2026-02-09 - Last updated in NVD database
Technical Details for CVE-2026-25497
Vulnerability Analysis
This vulnerability is classified as CWE-639: Authorization Bypass Through User-Controlled Key. The core issue lies in how the GraphQL API's saveAsset mutation handles authorization checks for asset operations. When processing a mutation request, the system correctly validates whether the authenticated user has permissions for the volume specified in the GraphQL schema. However, the actual asset retrieval occurs via a separate lookup using the asset ID parameter, which does not include a secondary validation to confirm the retrieved asset belongs to the volume the user is authorized to access.
This disconnect between authorization validation and resource retrieval creates a classic Insecure Direct Object Reference (IDOR) pattern within the GraphQL context. An attacker with legitimate write access to Volume A can craft a mutation targeting an asset ID belonging to Volume B (a restricted volume), and the system will permit the operation because authorization was checked against Volume A while the action is performed on Volume B's asset.
Root Cause
The root cause is a missing authorization check in the asset resolution logic within the GraphQL mutation handler. The saveAsset mutation in src/gql/resolvers/mutations/Asset.php validates user permissions based on the schema-defined volume context but fails to verify that the asset ID provided in the request actually belongs to that authorized volume before performing modifications.
Attack Vector
The attack is network-based and requires low-privilege authentication. An attacker needs:
- Valid credentials to authenticate with the Craft CMS instance
- Write access to at least one asset volume (even a low-privilege public volume)
- Knowledge of asset IDs in target restricted volumes (obtainable through enumeration or information disclosure)
The attacker crafts a malicious GraphQL mutation specifying their authorized volume in the schema context while targeting an asset ID from a restricted volume. The system authorizes the request based on the attacker's legitimate volume access, then retrieves and modifies the target asset without validating volume ownership.
// Security patch in src/gql/resolvers/mutations/Asset.php
// Source: https://github.com/craftcms/cms/commit/ac7edf868c1a81fd9c4dc49d3b3edf1cce113409
if (!$asset) {
throw new Error('No such asset exists');
}
+
+ if ($asset->volumeId !== $volume->id) {
+ $this->requireSchemaAction('volumes.' . $asset->getVolume()->uid, 'save');
+ }
} else {
$this->requireSchemaAction('volumes.' . $volume->uid, 'create');
The fix adds a critical check: after retrieving an asset by ID, the code now verifies whether the asset's volume ID matches the authorized volume. If not, it requires explicit authorization for the asset's actual volume, preventing cross-volume privilege escalation.
Detection Methods for CVE-2026-25497
Indicators of Compromise
- GraphQL mutation requests to the saveAsset endpoint that reference asset IDs outside the user's authorized volumes
- Unexpected asset modifications or transfers in restricted volumes by users who should not have access
- Audit logs showing users performing operations on volumes not assigned to their permission groups
Detection Strategies
- Monitor GraphQL API logs for saveAsset mutations and correlate asset IDs with the requesting user's volume permissions
- Implement anomaly detection for cross-volume asset operations that violate expected access patterns
- Review Craft CMS access logs for authenticated users performing bulk asset operations or accessing multiple volumes in rapid succession
Monitoring Recommendations
- Enable detailed GraphQL query logging to capture mutation parameters and user context
- Set up alerts for asset modifications in high-value or restricted volumes
- Implement file integrity monitoring on asset storage directories to detect unauthorized changes
How to Mitigate CVE-2026-25497
Immediate Actions Required
- Upgrade Craft CMS to version 4.17.0-beta.1 or later for the 4.x branch
- Upgrade Craft CMS to version 5.9.0-beta.1 or later, or stable release 5.8.22 or later for the 5.x branch
- Review asset volume permissions and audit recent asset modifications for signs of unauthorized access
- Consider temporarily disabling GraphQL API access for untrusted users until the patch is applied
Patch Information
The vulnerability has been patched in Craft CMS versions 4.17.0-beta.1 and 5.9.0-beta.1. A stable release patch is available in version 5.8.22. The fix adds proper volume ownership validation when processing asset mutations through the GraphQL API. For detailed patch information, see the GitHub Security Advisory and the commit changes.
Workarounds
- Restrict GraphQL API schema permissions to minimize the number of users with write access to any asset volume
- Implement network-level access controls to limit GraphQL endpoint exposure to trusted networks only
- Use custom middleware or firewall rules to validate asset IDs in mutations against user permissions before requests reach Craft CMS
# Configuration example - Disable GraphQL API temporarily in config/general.php
# Add or modify the following setting:
'enableGraphqlIntrospection' => false,
# For complete API disable (if not required):
'enableGql' => false,
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

