Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessAuthenticate as staff user with plugin-change permission
-
DeliveryPOST crafted move_plugin request with plugin_parent set to a descendant plugin ID
-
ExploitDatabase writes cyclic parent-child relationship to plugin tree
-
ExecutionSubsequent CMS rendering or management operation calls get_descendants()
-
Persist_get_descendants_cte recurses indefinitely, exhausting DB recursion limit
-
ImpactRequest worker stalls, CMS availability denied
Vulnerability Assessment
| Weakness |
CWE
ASVS 5.0
V15 - Secure Coding and Architecture Recursion depth limits
|
| Exploitation Conditions | Exploitation requires an authenticated staff-level Django user account (is_staff=True) with the change_plugin permission explicitly granted under django CMS's CMS_PERMISSION system - this permission is not granted by default to all staff users and must be assigned. The attacker must be able to POST to the move_plugin admin endpoint. The cyclic reparenting DoS is limited to move operations only; copy and cut-to-clipboard operations create new plugin instances and are not affected by this specific cycle vector. Anonymous users and authenticated non-staff users cannot reach this endpoint. The database must support recursive CTEs (PostgreSQL, MySQL 8+, SQLite 3.35+); databases without CTE support or with very low recursion depth limits will surface an error earlier but may still corrupt tree state. Organizations using CMS_PERMISSION with narrowly scoped per-placeholder grants to a small number of trusted editors face significantly lower realistic risk than those granting broad plugin-change permissions site-wide. |
| Impact | The CVSS 7.1 vector AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:H accurately reflects the threat profile: the attack is network-accessible, low-complexity, and requires no user interaction, but is gated behind authenticated staff access with the specific plugin-change permission under CMS_PERMISSION. The high availability impact (A:H) is credible - stalled request workers can cascade to full CMS unavailability. The low integrity impact (I:L) reflects persistent tree corruption in the database. EPSS score was not provided in the input data, so probabilistic exploitation likelihood cannot be assessed numerically. No CISA KEV listing was referenced, and no public proof-of-concept was identified, making this lower operational priority than an unauth or KEV-listed issue of similar CVSS. Real-world risk is meaningfully reduced by the PR:L constraint: anonymous users, regular authenticated CMS users, and even staff without plugin-change grants cannot exploit this. The primary threat model is a malicious or compromised internal staff account. Organizations that tightly scope CMS_PERMISSION grants face lower realistic risk than those granting broad plugin-change permissions across many users. |
| Exploit ScenarioDerived | An authenticated staff user with plugin-change permission logs into the django CMS admin interface and issues a crafted POST to the move_plugin endpoint, setting plugin_parent to the primary key of a child plugin that is already a descendant of the plugin being moved. The database writes the cyclic relationship, and any subsequent CMS operation that calls get_descendants() on the parent plugin - such as page rendering, a subsequent move, or a delete - triggers indefinite recursive CTE execution, stalling the database connection and the web worker thread for the duration, effectively denying service to other users. No public proof-of-concept exploit has been identified, but the attack is straightforward to reproduce from the pull request description and commit diff at https://github.com/django-cms/django-cms/pull/8645. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Aug 20, 2026
Uncontrolled recursion in django CMS prior to 5.0.8 allows an authenticated staff user to corrupt the plugin tree and deny service by exploiting a missing cycle guard in the move_plugin endpoint. By supplying the plugin's own primary key or a descendant's ID as the plugin_parent value in a crafted POST request, the attacker creates a parent-child cycle that causes the _get_descendants_cte and _get_ancestors_cte recursive CTE queries to loop indefinitely, exhausting database recursion limits and consuming web request workers. The same 5.0.8 release also patches a related information disclosure path where clipboard copy operations lacked source-side permission checks, allowing a staff user to exfiltrate plugin content from placeholders they have no access to - consistent with the 'Information Disclosure' tag on this advisory. No public exploit identified at time of analysis.
RemediationAI
Upgrade django CMS to version 5.0.8 or later, the confirmed fixed release available at https://github.com/django-cms/django-cms/releases/tag/5.0.8 and via PyPI. The patch introduces a pre-move cycle check in move_plugin that calls plugin._get_descendants_ids() and returns HTTP 400 if the target parent is the plugin itself or any descendant, preventing the cycle from being written to the database. If immediate upgrade is not possible, restrict the change_plugin permission under CMS_PERMISSION to the minimum set of highly trusted staff accounts - this limits the attack surface to users who genuinely require reparenting capability. A web application firewall rule blocking POST requests to the move_plugin admin endpoint for all but named IP ranges provides an additional layer, but introduces operational friction for legitimate CMS editors. There is no known workaround that addresses the root cause without upgrading; compensating controls only reduce exposure by restricting who can reach the endpoint.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in pypi
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
django CMS is a Django-based enterprise content management system that stores page content as a hierarchical tree of plugin objects in a relational database. The move_plugin endpoint in cms/admin/placeholderadmin.py handles reparenting of these plugin nodes and prior to 5.0.8 accepted any integer as plugin_parent without verifying that the supplied value was not the plugin itself or one of its own descendants. The tree traversal functions _get_descendants_cte and _get_ancestors_cte in cms/models/pluginmodel.py implement recursive CTEs (Common Table Expressions) at the database layer to walk the tree, but contained no termination logic for cyclic graphs. CWE-674 (Uncontrolled Recursion) captures this root cause precisely: once a cycle is inserted into the tree, any subsequent call to get_descendants() - whether triggered by rendering, copy, or delete operations - enters infinite recursion or hits the database engine's maximum recursion depth, leaving the tree in a corrupted state and stalling the web worker that processed the request. The fix in commit 7642a98 adds a pre-move guard in move_plugin that calls plugin._get_descendants_ids() and rejects (HTTP 400) any request where target_parent.pk equals the plugin's own pk or appears in its descendant set.
Know when Python 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
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:H
Network endpoint requires authenticated staff with plugin-change permission (PR:L, AV:N); tree corruption is low integrity (I:L) and worker exhaustion is high availability (A:H); no confidentiality impact from the primary DoS vector.
Primary rating from Vendor (github).
CVSS VectorVendor: github
Lifecycle Timeline
2DescriptionCVE.org
django CMS is an easy-to-use and developer-friendly enterprise content management system powered by Django. Prior to 5.0.8, the move_plugin endpoint in cms/admin/placeholderadmin.py accepts an attacker-controlled plugin_parent value without rejecting a plugin’s own identifier or a descendant identifier. A staff user with plugin-change permission under CMS_PERMISSION can create a parent_id cycle in the plugin tree. The _get_descendants_cte and _get_ancestors_cte queries in cms/models/pluginmodel.py have no cycle guard, so get_descendants() and later rendering, copy, or delete operations can recurse indefinitely or reach a database recursion limit, corrupting the tree and consuming request workers. This issue is fixed in versions 5.0.8.
Articles & Coverage 1
Executive ViewAI
Django CMS versions prior to 5.0.8 create dual operational and security risks: staff-level access can trigger CMS-wide outages or enable unauthorized retrieval of restricted content management data. Organizations should prioritize immediate assessment and patching to maintain CMS stability and access control integrity.
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
Information disclosure occurs when an application unintentionally exposes sensitive data that aids attackers in reconnaissance or directly compromises security.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
EUVD-2026-63565
GHSA-8jj7-4v57-frf5
NVD
CVE.org
EPSS
Vulnrichment
VulDB
Exploit-DB