CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-25497

Craft CMS: The Old GraphQL Switcheroo

Alon Barad
Alon Barad
Software Engineer

Feb 9, 2026·5 min read·33 visits

Executive Summary (TL;DR)

Classic IDOR/Logic flaw. The system checks if you have permission for Volume A, but lets you modify an Asset from Volume B. If you can upload files anywhere, you can mess with files everywhere. Fixed in 5.8.22.

A high-severity privilege escalation vulnerability in Craft CMS allows authenticated users with write access to any asset volume to manipulate assets in volumes they shouldn't be able to touch. By exploiting a logic flaw in the GraphQL `saveAsset` mutation, attackers can bypass authorization checks and modify, move, or delete restricted files.

The Hook: "I Have a Key, Does It Matter Which Door?"

Access control is hard. It's even harder when you're juggling graph-based data structures where relationships aren't always explicitly enforced at the gate. CVE-2026-25497 is a perfect example of what I like to call the "Bouncer Blindspot."

Imagine walking into a high-security office building. The guard at the front desk checks your badge. "Oh, you work in the mailroom? Go right ahead." You walk past the mailroom and stroll right into the CEO's office. The guard checked who you were and where you said you were going, but nobody followed you to make sure you actually went there.

In technical terms, this is a logic flaw in Craft CMS's GraphQL API. Specifically, the saveAsset mutation. It suffers from a classic dissociation between the authorization object and the target object. It's a high-severity issue (CVSS 8.6) because it turns low-privileged users—content editors, interns, or compromised accounts—into asset administrators for the entire system.

The Flaw: A Tale of Two Arguments

The vulnerability lives in the gap between Verification and Action. The saveAsset mutation in Craft's GraphQL API takes two critical arguments: a volume ID and an asset ID.

The logic flow went something like this:

  1. The user says, "I want to save this Asset (ID: 500) into this Volume (ID: 1)."
  2. The system asks, "Does this user have permission to write to Volume 1?"
  3. The permissions system says, "Yes, Volume 1 is the Public Uploads folder. They have access."
  4. The system then fetches Asset 500.
  5. The system saves the changes to Asset 500.

Spot the problem? The code verified rights on the Volume passed in the arguments, but it performed the operation on the Asset passed in the arguments. It never stopped to ask, "Wait a minute, does Asset 500 actually belong to Volume 1?"

If Asset 500 is actually in Volume 99 (Restricted HR Documents), the system didn't care. It was too busy looking at the permissions for Volume 1. This is a textbook CWE-639: Authorization Bypass Through User-Controlled Key.

The Code: The Smoking Gun

Let's look at the PHP code responsible for this mess. This resides in src/gql/resolvers/mutations/Asset.php.

The Vulnerable Code:

// It checks permissions on the provided volume ($volume)
$this->requireSchemaAction('volumes.' . $volume->uid, 'save');
 
// Then it fetches the asset by ID, ignoring the volume context
$asset = Asset::find()->id($arguments['id'])->one();
 
if (!$asset) {
    throw new Error('No such asset exists');
}
 
// Proceeds to save $asset...

The developer trusted the client to provide a matching pair of Volume ID and Asset ID. Never trust the client. The client is a liar.

The Fix (Commit ac7edf8):

The patch adds a sanity check. If the Asset's actual Volume ID doesn't match the Volume ID passed in the request, it forces a new permission check against the real volume.

// ... asset fetched ...
 
if ($asset->volumeId !== $volume->id) {
    // Oh, you're trying to reach across volumes?
    // Let's check if you have rights for the REAL volume.
    $this->requireSchemaAction('volumes.' . $asset->getVolume()->uid, 'save');
}

This simple if statement closes the gap. It forces the authorization context to switch to the asset's actual location, effectively slamming the door on the exploit.

The Exploit: Moving the Furniture

Exploiting this is trivially easy if you have a valid account with write access to any volume. Let's say you are a low-level editor allowed to upload images to the "Blog Images" volume.

Step 1: Reconnaissance You need two things: the ID of a volume you own (e.g., volumeId: 10) and the ID of an asset you want to mess with (e.g., assetId: 1337). You can often enumerate asset IDs just by incrementing numbers or looking at the site's predictable usage of GraphQL queries.

Step 2: The Attack You construct a GraphQL mutation. You tell the system you are operating in the context of your allowed volume, but you target the restricted asset.

mutation {
  saveAsset(
    volumeId: 10,       # Your allowed volume
    id: 1337,           # The CEO's private tax return (actually in Volume 1)
    title: "HACKED_BY_INTERN"
  ) {
    id
    title
  }
}

Step 3: The Impact The server checks if you can write to Volume 10. You can. It then updates Asset 1337 with your new title.

Even worse, saveAsset can handle file moves. You could potentially change the newLocation of the asset, effectively moving a private document into your public "Blog Images" folder, allowing you to download it. This escalates the issue from "Defacement" to "Data Exfiltration."

The Fix: Patch or Perish

There is no fancy workaround here. You need to patch. The logic flaw is deep in the resolver code.

Upgrade Paths:

  • Craft CMS 4: Update to 4.17.0-beta.1 or later.
  • Craft CMS 5: Update to 5.8.22 or 5.9.0-beta.1 or later.

If you absolutely cannot patch immediately (why?), your only mitigation is to strip write permissions from everyone untrusted. If a user has no write access to any volume, they cannot pass the initial check, and the exploit chain fails. But seriously, just update the CMS.

Official Patches

Craft CMSGitHub Commit fixing the issue
Craft CMSRelease notes for version 5.8.22

Fix Analysis (1)

Technical Appendix

CVSS Score
8.6/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N

Affected Systems

Craft CMS 4.x (prior to 4.17.0-beta.1)Craft CMS 5.x (prior to 5.8.22)

Affected Versions Detail

Product
Affected Versions
Fixed Version
Craft CMS
Pixel & Tonic
>= 4.0.0-RC1, < 4.17.0-beta.14.17.0-beta.1
Craft CMS
Pixel & Tonic
>= 5.0.0-RC1, < 5.8.225.8.22
AttributeDetail
CWE IDCWE-639
Attack VectorNetwork (GraphQL)
CVSS Score8.6 (High)
ImpactPrivilege Escalation / Data Manipulation
PrerequisitesAuthenticated user with write access to at least one volume
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1222File and Directory Permissions Modification
Defense Evasion
T1078Valid Accounts
Initial Access
T1565Data Manipulation
Impact
CWE-639
Authorization Bypass Through User-Controlled Key

The application authorizes a user based on a provided key (Volume ID) but performs the action on a different object (Asset ID) without verifying the relationship between the two.

Known Exploits & Detection

HypotheticalExploitation requires crafting a GraphQL mutation with mismatched volumeId and assetId arguments.

Vulnerability Timeline

Fix commit pushed to repository
2026-01-09
CVE Published
2026-02-09
GHSA Advisory Released
2026-02-09

References & Sources

  • [1]GHSA-fxp3-g6gw-4r4v
  • [2]NVD CVE-2026-25497

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•1 day ago•CVE-2026-9354
6.9

CVE-2026-9354: Arbitrary Mass Mention Bypass in NousResearch hermes-agent Slack and Mattermost Adapters

A vulnerability in the Slack and Mattermost platform adapters for NousResearch hermes-agent permits an unauthenticated remote attacker to execute arbitrary mass mentions. By leveraging prompt injection, an attacker can bypass output sanitization logic and trigger workspace-wide notification exhaustion.

Alon Barad
Alon Barad
23 views•6 min read
•2 days ago•CVE-2026-9306
6.3

CVE-2026-9306: Unauthenticated Insecure Direct Object Reference (IDOR) in QuantumNous new-api Midjourney Relay

CVE-2026-9306 is a critical unauthenticated Insecure Direct Object Reference (IDOR) vulnerability located in the QuantumNous new-api application, affecting versions up to and including 0.12.1. The flaw is caused by improper middleware ordering combined with a lack of object-level authorization checks. This allows remote, unauthenticated attackers to retrieve sensitive Midjourney images belonging to other users by supplying a valid task identifier.

Amit Schendel
Amit Schendel
8 views•5 min read
•3 days ago•GHSA-GGXF-37HM-9WQF
6.5

GHSA-GGXF-37HM-9WQF: Session Leakage via Unsafe Challenge Path Parsing in instagrapi

The instagrapi library prior to version 2.6.9 contains an improper input validation vulnerability within its challenge handling mechanism. Maliciously crafted server responses can manipulate the client into forwarding session cookies and credentials to an external attacker-controlled domain.

Amit Schendel
Amit Schendel
20 views•6 min read
•3 days ago•GHSA-QQQM-5547-774X
9.1

GHSA-QQQM-5547-774X: Unauthenticated Path Traversal in FileBrowser Quantum PATCH Handler

GHSA-QQQM-5547-774X is a critical path traversal vulnerability in the FileBrowser Quantum application, specifically within the Go backend package. The vulnerability resides in the HTTP handler responsible for processing bulk file modifications via the public API. Unauthenticated attackers can exploit an order-of-operations flaw in the path sanitization logic to bypass intended directory restrictions. This allows adversaries to arbitrarily read, move, and overwrite files on the underlying filesystem by supplying specially crafted HTTP PATCH requests.

Alon Barad
Alon Barad
4 views•6 min read
•3 days ago•CVE-2026-8723
5.3

CVE-2026-8723: Synchronous Denial of Service in qs npm Package via TypeError

The qs query string parsing and serialization library for Node.js is vulnerable to a synchronous Denial of Service (DoS) attack. The vulnerability manifests as a process-terminating TypeError when processing arrays with null or undefined elements under specific configuration parameters.

Amit Schendel
Amit Schendel
33 views•7 min read
•3 days ago•GHSA-7M8F-HGJQ-8GC9
7.5

GHSA-7M8F-HGJQ-8GC9: Pre-Authentication Denial of Service via Insecure Deserialization Order in aiosend

The aiosend library prior to version 3.0.6 contains a pre-authentication Denial of Service (DoS) vulnerability in its webhook handling mechanism. The software processes and deserializes incoming JSON payloads before verifying the cryptographic signature, allowing unauthenticated attackers to exhaust server CPU and memory resources by sending large, complex payloads.

Amit Schendel
Amit Schendel
3 views•6 min read