Jun 19, 2026·6 min read·3 visits
Unauthenticated remote attackers can dump the entire nested page structure and elements of Alchemy CMS via a missing authorization check on the API nested pages endpoint.
A critical missing authorization vulnerability exists in the API Pages Controller of Alchemy CMS. An unauthenticated remote attacker can exploit the 'nested' action to retrieve the entire nested page tree. Furthermore, by appending the query parameter '?elements=true', the attacker can extract sensitive content from draft, unpublished, and restricted pages, bypassing all access controls.
Alchemy CMS relies on an API-driven architecture to deliver content to headless frontends. The Api::PagesController manages the retrieval of page objects and their associated hierarchies. Under default operations, the application is expected to restrict access to unpublished nodes, drafts, and member-only sections unless a user possesses an authenticated session with sufficient privileges.
The API exposes several endpoints to allow external clients to reconstruct the site structure. One such endpoint is the nested action, which returns a structured page tree. Because this action is exposed to the public network, it represents a high-priority attack surface for automated enumeration and targeted information harvesting.
The vulnerability manifests as a complete omission of authorization validation within this API pathway. Unauthenticated remote actors can access the nested endpoint to bypass individual page access controls. The resulting behavior is the extraction of restricted structural data and sensitive text assets from database records.
The root cause of this vulnerability lies in the missing enforcement of access control policies within Api::PagesController#nested. While security policies are correctly declared via CanCanCan rules on sibling endpoints like show and index, the nested action completely bypassed these checks. The controller processed requests for nested page trees without evaluating user sessions or invoking permission validation libraries.
Database queries executed during the processing of this endpoint were entirely unscoped. The PageTreePreloader service class queried the self_and_descendants Active Record association directly from the page model. Because the database query lacked scoping constraints like .accessible_by(current_ability, :read), the application loaded all descendants into memory regardless of their status.
The data serialization layer introduced an additional point of failure. When the query parameter ?elements=true was specified, PageTreeSerializer automatically retrieved and appended elements associated with each node. The serializer did not verify whether the active session had permission to read the parent page, leading to the direct disclosure of restricted text, configurations, and metadata.
A direct comparison of the vulnerable and patched code paths demonstrates how the authorization gap was closed. The primary controller modification introduces a direct authorization call using CanCanCan integration before constructing the preloader instance.
# Vulnerable Controller Implementation
def nested
@page = Page.find_by(id: params[:page_id]) || Language.current_root_page
preloaded_page = PageTreePreloader.new(page: @page, user: current_alchemy_user).call
# ...
end# Patched Controller Implementation
def nested
@page = Page.find_by(id: params[:page_id]) || Language.current_root_page
authorize! :show, @page
preloaded_page = PageTreePreloader.new(
page: @page,
user: current_alchemy_user,
ability: current_ability
).call
# ...
endThe PageTreePreloader class was updated to accept the active user's ability context. This context is then applied directly to the Active Record relation using the .accessible_by scope, ensuring that only authorized pages are queried from the database layer.
# Patched Preloader Query Scoping
def call
pages = page.self_and_descendants.accessible_by(ability, :read)
# ...
endExploitation of this vulnerability is straightforward and requires no prior authentication or specialized tools. An attacker can map the complete structure of an Alchemy CMS instance using a single unauthenticated HTTP GET request. This mapping reveals unpublished pages, hidden drafts, and restricted member directories.
To initiate the attack, a client queries the nested API endpoint. The server responds with the complete JSON hierarchy of pages, including elements marking nodes as restricted or public.
curl -s http://localhost:3000/api/pages/nested | grep -E '"name"|"restricted"'To extract the actual text content and sensitive elements from these restricted pages, the attacker appends the elements query parameter. This forces the server to serialize and return the internal elements of all listed pages, including those behind authorization barriers.
curl -s "http://localhost:3000/api/pages/nested?elements=true"The efficacy of this bypass can be verified by attempting a direct request to the show API endpoint for a restricted page. The target endpoint correctly enforces authorization and returns a 403 Forbidden status, while the nested action returns the same data without restriction.
The security impact of this vulnerability is high. It permits unauthenticated remote actors to bypass access controls, compromising the confidentiality of all content stored within the CMS database. This includes embargoed marketing copy, internal documentation, confidential product specs, and proprietary corporate communications.
Because the vulnerability affects a core API endpoint, automated scanners can easily discover and exploit exposed installations. The CVSS score of 7.5 reflects high impact to confidentiality, with no impact to integrity or availability. The vulnerability does not require user interaction or elevated privileges to execute.
CVSS v3.1 Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
No evidence of active exploitation in ransomware campaigns has been recorded, and the vulnerability is not currently listed on the CISA Known Exploited Vulnerabilities catalog. However, the availability of public proof-of-concept material increases the risk of opportunistic exploitation by threat actors mapping web assets.
Remediation requires upgrading the alchemy_cms gem to a patched version. Security administrators must identify the current major and minor release branch of their installation and apply the corresponding patch.
For systems running on the 8.2 branch, upgrade to version 8.2.6 or higher. For systems on the 8.1 branch, upgrade to version 8.1.14 or higher. For systems on the 8.0 branch, upgrade to 8.0.15 or higher. For legacy deployments on the 7.4 branch, upgrade to 7.4.15 or higher.
If immediate patching is not possible, a temporary hotfix can be applied by creating a Rails initializer. This initializer intercepts incoming requests to the nested pages API and enforces basic role-based access checks.
# config/initializers/alchemy_api_nested_hotfix.rb
ActiveSupport.on_load(:action_controller) do
before_action if: -> { request.path == "/api/pages/nested" } do
unless current_alchemy_user&.has_role?(:author, :admin)
render json: { error: "Forbidden" }, status: :forbidden
end
end
endThe official fix is complete. By applying authorization checks at the controller level, scoping database queries in the preloader service, and validating abilities inside the serializer, the developers implemented a defense-in-depth strategy that prevents variant exploitation.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
alchemy_cms AlchemyCMS | <= 7.4.14 | 7.4.15 |
alchemy_cms AlchemyCMS | >= 8.0.0.a, <= 8.0.14 | 8.0.15 |
alchemy_cms AlchemyCMS | >= 8.1.0, <= 8.1.13 | 8.1.14 |
alchemy_cms AlchemyCMS | >= 8.2.0, <= 8.2.5 | 8.2.6 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-862 (Missing Authorization) |
| Attack Vector | Network (Unauthenticated) |
| CVSS Score | 7.5 (High) |
| Exploit Status | Proof-of-concept (PoC) available |
| KEV Status | Not listed |
| Impact | Full disclosure of unpublished, draft, and restricted pages and elements |
The software does not perform an authorization check when an actor attempts to access a resource or perform an action.
A critical SQL injection vulnerability was discovered in TypeORM's UpdateQueryBuilder and SoftDeleteQueryBuilder when targeting MySQL and MariaDB backends. The flaw allows unauthenticated remote attackers to execute arbitrary SQL commands because input validation was bypassed on certain method signatures. The initial patch was incomplete, leaving a bypass open, which was resolved in the final security update.
Hugo versions v0.123.0 through v0.163.0 are vulnerable to a directory confinement bypass. A regression in the virtual filesystem layer causes symbolic links to be followed during template execution, allowing templates to read arbitrary host files.
Nokogiri is a popular Ruby gem used for parsing XML and HTML documents. A Use-After-Free (UAF) vulnerability exists in its CRuby implementation during XInclude processing. When an application traverses an XML document and exposes nodes to Ruby before calling `do_xinclude`, the underlying C library `libxml2` can free these structures in-place. This leaves active Ruby objects holding pointers to freed memory, leading to potential segmentation faults, memory corruption, or information disclosure.
A use-after-free (UAF) vulnerability exists in the CRuby native extension of the Nokogiri gem when updating XML attribute values. If child nodes of an XML attribute are wrapped by Ruby objects prior to setting the attribute's value, the underlying C memory structures are freed while the Ruby wrapper retains a dangling pointer. This results in memory corruption, invalid pointer dereferences, and application crashes during execution or garbage collection.
A client-side Stored Cross-Site Scripting (XSS) vulnerability exists in the JupyterLab Extension Manager. This vulnerability allows an attacker to register a malicious package on the Python Package Index (PyPI) with a crafted metadata homepage URL using the 'javascript:' pseudo-protocol. When a JupyterLab user opens the Extension Manager and clicks the extension name, the browser executes arbitrary JavaScript code within the context of the JupyterLab origin. This can lead to the theft of active workspace documents, credentials, and API tokens. The issue affects all versions of JupyterLab prior to version 4.5.9.
An arbitrary Remote Code Execution (RCE) vulnerability exists in ouroboros-ai due to an incomplete fix for CVE-2026-47211. Ouroboros automatically loads environment configurations from local .env files located in the current working directory (CWD) of cloned repositories. Although a denylist (_UNTRUSTED_ENV_DENYLIST) was introduced in version 0.39.0 to filter out execution-routing environment variables, multiple critical configuration variables were omitted, enabling complete sandbox bypass and arbitrary system command execution.