Aug 21, 2026·7 min read·2 visits
A missing object-level permission check in Wagtail's page translation endpoint allows authenticated users with global translation rights to duplicate and read restricted pages, bypass access controls, and extract sensitive content.
An authenticated user with global translation permissions can exploit a missing authorization check on the page translation endpoint in Wagtail CMS. This allows the attacker to copy and view pages they do not have explicit edit or explore access to.
Wagtail is an open-source Content Management System (CMS) built on the Django framework. The platform structures content hierarchically as pages, with access controls governed by an object-level permissions model. This design ensures that users can only interact with sections of the site tree for which they have explicit authorization. Among its localization features, Wagtail supports multi-language workflows through its translation framework, specifically implemented in the simple translation module.
The translation copy endpoint is a key component of this localization framework, designed to allow authorized users to duplicate content from one locale to another. To perform this action, a user must possess a global permission allowing translation submissions. This architecture creates an attack surface where a low-privileged authenticated user with global translation rights can interact with arbitrary page objects if the endpoint does not properly validate object-level access controls.
The vulnerability, identified as GHSA-jm5p-837g-rv8g, resides in this specific endpoint. Due to a missing authorization check, a user possessing only the global translation privilege can issue requests to translate any arbitrary page ID. This constitutes an Insecure Direct Object Reference (IDOR) vulnerability, also classified as Broken Object Level Authorization (BOLA), allowing unauthorized read access to restricted page hierarchies.
The root cause of this vulnerability lies in the divergence between global permission verification and object-level permission enforcement within Django and Wagtail. Django applications frequently utilize global model-level permissions to control broad actions, such as whether a user can add, change, or delete any instance of a model. Wagtail complements this with granular, tree-based hierarchical permissions to restrict access to specific subsets of pages.
In the vulnerable implementation, the API view handling the translation copy request only validated the requesting user's global permission. It verified that the user possessed the general translation submission permission. However, once this check passed, the code proceeded to fetch and copy the target page using its database identifier without verifying if the user had permission to view or edit that specific page instance.
Because Wagtail copies the page into a workspace or locale where the low-privileged user possesses editing privileges, the user can subsequently access the copied instance. This indirect data leakage permits the unauthorized user to read the draft status, metadata, and full body content of pages they are restricted from accessing in the primary tree. The application essentially acts as a confused deputy, using its elevated privileges to duplicate restricted pages into an insecure context on behalf of the attacker.
To understand the vulnerability mechanism, we compare the vulnerable logical flow with the patched implementation. In the vulnerable version, the request is processed directly after verifying the global permission, bypassing the page-specific permissions checks defined by the Wagtail permissions engine.
# Vulnerable conceptual implementation
from django.core.exceptions import PermissionDenied
from wagtail.models import Page
def copy_page_for_translation(request, page_id, target_locale):
# Only global permission is checked
if not request.user.has_perm("simple_translation.submit_translation"):
raise PermissionDenied("Missing global translation permission")
# Target page retrieved directly by ID, ignoring object-level hierarchy permissions
page = Page.objects.get(id=page_id)
# The page content is duplicated into the new locale context
new_page = page.copy(to_locale=target_locale)
return new_pageThe patched version corrects this logic gap by enforcing object-level authorization before executing the duplication. The code retrieves the page and requests the user's specific permissions for that object. If the user lacks exploration or editing privileges on the source page, the application raises a permission denied exception.
# Patched conceptual implementation
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404
from wagtail.models import Page
def copy_page_for_translation(request, page_id, target_locale):
# 1. Enforce global translation permission
if not request.user.has_perm("simple_translation.submit_translation"):
raise PermissionDenied("Missing global translation permission")
# 2. Retrieve the target page safely
page = get_object_or_404(Page, id=page_id)
# 3. CRITICAL FIX: Verify the user has sufficient rights to access the source page
user_page_perms = page.permissions_for_user(request.user)
if not user_page_perms.can_edit() and not user_page_perms.can_describe():
# If the user cannot edit or view the page in the explorer tree, reject the request
raise PermissionDenied("You do not have permission to view or edit this page")
# 4. Proceed with duplication only after passing both validation layers
new_page = page.copy(to_locale=target_locale)
return new_pageThis fix ensures that the user cannot interact with any database object via this API unless their role explicitly authorizes them to access that specific node in the Wagtail tree.
Exploitation of this vulnerability requires an authenticated session belonging to a user account with the globally assigned translation submission permission. An attacker begins by identifying the numerical identifier of a restricted or draft page. While the target page ID is not directly visible to the attacker in the CMS explorer, it can often be obtained through brute-force enumeration, identifier leakage in other public-facing components, or standard application metadata analysis.
Once the target ID is acquired, the attacker submits a direct POST request to the translation copy API endpoint, passing the target page ID and a desired destination locale. Because the endpoint does not validate if the attacker has view or edit rights to the source page, the request completes successfully.
POST /admin/translation/copy/ HTTP/1.1
Host: target-cms.local
Authorization: Session <AuthenticatedSessionToken>
Content-Type: application/json
{
"page_id": 1042,
"target_locale": "fr"
}Following the successful response, the backend creates a duplicate of page 1042 in the French workspace. If the attacker has editing permissions for the French locale tree, they can open the newly generated page. The attacker can then read all sensitive information contained in the original page, which may include unreleased drafts, restricted portal guidelines, or database metadata.
The primary security impact of this vulnerability is the unauthorized exposure of confidential information (CWE-862). Since the duplication process copies all page fields, including draft elements and metadata, an attacker can completely reconstruct restricted pages. This is highly critical in corporate deployments where draft pages are used to prepare pre-release announcements, regulatory filings, or internal policy documents.
Because this vulnerability is restricted to data extraction, it does not directly compromise data integrity or system availability. The attacker cannot modify the source page, nor can they execute arbitrary code on the underlying host. Consequently, the CVSS v3.1 score is calculated as 6.5, reflecting high confidentiality impact with no integrity or availability degradation.
The attack vector is network-based and has low complexity, but is mitigated by the requirement for authenticated access. In organizations that enforce strict privilege segregation, this flaw allows low-privileged editors or external translators to escalate their read privileges horizontally and vertically across the CMS hierarchy.
The primary and recommended remediation is to upgrade Wagtail to the appropriate patched release. Maintenance branches have been updated to address this flaw. Administrators should upgrade to one of the following versions depending on their current release path: 7.0.9, 7.3.4, 7.4.3, or 8.0rc2.
If upgrading immediately is not feasible, organizations can implement manual mitigations to reduce the exposure. The most effective administrative mitigation is to temporarily revoke the translation submission permission from all users who do not require immediate access. Alternatively, organizations can implement custom middleware within their Django configuration to intercept calls to the translation endpoints and validate page-level permissions before handing execution to the view.
Additionally, security teams should review Web Application Firewall (WAF) logs and application audit logs for unauthorized page copy events. Multiple requests to the translation endpoint containing a sequence of page IDs from a single low-privileged account should be treated as potential exploitation and indicator of a manual or automated compromise attempt.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
wagtail Wagtail | < 7.0.9 | 7.0.9 |
wagtail Wagtail | >= 7.1, < 7.3.4 | 7.3.4 |
wagtail Wagtail | >= 7.4, < 7.4.3 | 7.4.3 |
wagtail Wagtail | == 8.0rc1 | 8.0rc2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-862 (Missing Authorization) |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 | 6.5 (Medium) |
| Exploit Status | PoC Concepts Documented |
| Vulnerability Class | IDOR / Broken Object Level Authorization (BOLA) |
| Affected Component | wagtail.contrib.simple_translation |
The software does not perform an authorization check when an actor attempts to access a resource or perform an action.
An uncontrolled resource allocation vulnerability (CWE-770) affects Mailpit SMTP server versions 1.30.0 through 1.30.4. The vulnerability is located within the DATA parsing logic, where an unauthenticated remote attacker can stream an endless sequence of bytes devoid of newline characters. Because line size limits are evaluated only after buffer completion, the Go runtime repeatedly allocates memory on the heap to store the single oversized line, causing resource exhaustion and an Out-Of-Memory termination of the service process.
A critical cross-site WebSocket hijacking (CSWSH) vulnerability in Mailpit allows malicious websites to bypass CORS security controls via URL-encoded path mismatches, exposing sensitive development SMTP communications to unauthorized actors.
A critical vulnerability in Dgraph Alpha allows unauthenticated network clients to delete and replace database stores. The public gRPC interface on port 9080 processes external snapshot streams without enforcing authentication or authorization, triggering immediate database destruction via the storage engine's initialization process.
A security vulnerability in Copier versions 9.5.0 through 9.15.1 allows unauthenticated remote code execution via crafted HTTP requests or local paths containing traversal sequences. The trust-evaluation mechanism compares target repository paths or URLs against trusted prefixes using unnormalized string comparison, while the subsequent fetching mechanism normalizes the path before cloning. Attackers can exploit this asymmetry to bypass security warning prompts and execute arbitrary commands under the local user context.
GeoLens before version 1.2.4 contains multiple critical-tier security vulnerabilities including improper authorization in metadata access, tile cache scope leakage, dataset title enumeration, weak default credentials, and denial of service via STAC POST search.
CVE-2026-55694 is a chained Information Disclosure and Insecure Direct Object Reference (IDOR) vulnerability in Snipe-IT prior to version 8.6.3. The vulnerability allows authenticated, restricted users to completely bypass randomized file-naming security controls, leak the obfuscated filenames of signed End User License Agreements (EULAs), and subsequently download these confidential documents across tenant boundaries.