Every CVE Search/ Get API key

CVE-2026-57579

Alchemy: Unauthenticated nested page API leaks restricted & unpublished content

7.5 HighFix available

Alchemy is an open source content management system engine written in Ruby on Rails. Prior to 7.4.15, 8.0.15, 8.1.14, and 8.2.6, the unauthenticated GET /api/pages/nested endpoint implemented by Api::PagesController#nested in app/controllers/alchemy/api/pages_controller.rb returns an unfiltered page tree because it performs no authorization and does not scope descendants by the caller's ability. Anonymous callers can retrieve restricted and unpublished page metadata that the sibling show action denies. When elements=true is supplied, PageTreeSerializer also returns element and ingredient content from restricted pages because PageTreePreloader and the serializer do not apply an ability check to those records. This issue is fixed in versions 7.4.15, 8.0.15, 8.1.14, and 8.2.6.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
None
Availability
None

Exploit likelihood

0.65%Up 0.2 points since Sep 15, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.5

Alchemy: Unauthenticated nested page API leaks restricted & unpublished content

Alchemy is an open source content management system engine written in Ruby on Rails. Prior to 7.4.15, 8.0.15, 8.1.14, and 8.2.6, the unauthenticated GET /api/pages/nested endpoint implemented by Api::PagesController#nested in app/controllers/alchemy/api/pages_controller.rb returns an unfiltered page tree because it performs no authorization and does not scope descendants by the caller's ability. Anonymous callers can retrieve restricted and unpublished page metadata that the sibling show action denies. When elements=true is supplied, PageTreeSerializer also returns element and ingredient content from restricted pages because PageTreePreloader and the serializer do not apply an ability check to those records. This issue is fixed in versions 7.4.15, 8.0.15, 8.1.14, and 8.2.6.

Record
CVE-2026-57579
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-862
Updated
2026-11-02
EUVDEUVD-2026-77637 7.5

Alchemy is an open source content management system engine written in Ruby on Rails. Prior to 7.4.15, 8.0.15, 8.1.14, and 8.2.6, the unauthenticated GET /api/pages/nested endpoint implemented by Api::PagesController#nested in app/controllers/alchemy/api/pages_controller.rb returns an unfiltered page tree because it performs no authorization and does not scope descendants by the caller's ability. Anonymous callers can retrieve restricted and unpublished page metadata that the sibling show action denies. When elements=true is supplied, PageTreeSerializer also returns element and ingredient content from restricted pages because PageTreePreloader and the serializer do not apply an ability check to those records. This issue is fixed in versions 7.4.15, 8.0.15, 8.1.14, and 8.2.6.

Record
EUVD-2026-77637
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-mqq5-j7w8-2hgh 7.5

AlchemyCMS: Unauthenticated nested page API leaks restricted & unpublished content

Unauthenticated nested page API leaks restricted & unpublished content

  • Location: app/controllers/alchemy/api/pages_controller.rb:28 (Api::PagesController#nested)
  • Affected version: Alchemy CMS 8.3.0.dev (Rails 8.1.3)

Description

The unauthenticated GET /api/pages/nested endpoint returns the full page tree to any anonymous caller, including restricted (member-only) pages and unpublished/draft pages that should be hidden. Appending ?elements=true additionally dumps the element/ingredient content of restricted pages, fully bypassing the access control the sibling show and index actions enforce.

Root cause

Api::PagesController#nested calls no authorize! and applies no published/restricted scoping, unlike show (authorize! :show) and index (accessible_by(current_ability, :index)). PageTreePreloader loads page.self_and_descendants unfiltered, and PageTreeSerializer emits every page's metadata (and, with elements, public_version.elements) with no ability check.

Evidence

An unauthenticated GET /api/pages/nested returns HTTP 200 with the restricted page ("restricted":true) and an unpublished draft ("public":false); ?elements=true leaks its content (e.g. TOPSECRET_RESTRICTED_BODY_proof123). The same guest hitting GET /api/pages/3 (show) gets HTTP 403 {"error":"Not authorized"}, proving nested returns what show correctly denies.

Reproduction

# 1) Metadata leak (guest, no auth)
curl -s http://localhost:3000/api/pages/nested | python3 -m json.tool | grep -E '"name"|"restricted"|"public"'

# 2) Content leak of restricted page
curl -s "http://localhost:3000/api/pages/nested?elements=true" | grep -oE 'TOPSECRET_RESTRICTED_BODY_[A-Za-z0-9]+|RESTRICTED_RICHTEXT_[A-Za-z0-9]+'

# 3) Contrast — show denies the same guest
curl -s -o /dev/null -w "show /api/pages/3 -> HTTP %{http_code}\n" http://localhost:3000/api/pages/3

Suggested fix

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
  render json: PageTreeSerializer.new(preloaded_page, ability: current_ability,
                                      user: current_alchemy_user, elements: params[:elements])
end

Additionally scope PageTreePreloader's self_and_descendants via accessible_by(current_ability) and gate element emission in PageTreeSerializer#page_elements behind opts[:ability].can?(:show, page).

Record
GHSA-mqq5-j7w8-2hgh
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-862
Updated
2026-11-02
NVD 7.5

Alchemy is an open source content management system engine written in Ruby on Rails. Prior to 7.4.15, 8.0.15, 8.1.14, and 8.2.6, the unauthenticated GET /api/pages/nested endpoint implemented by Api::PagesController#nested in app/controllers/alchemy/api/pages_controller.rb returns an unfiltered page tree because it performs no authorization and does not scope descendants by the caller's ability. Anonymous callers can retrieve restricted and unpublished page metadata that the sibling show action denies. When elements=true is supplied, PageTreeSerializer also returns element and ingredient content from restricted pages because PageTreePreloader and the serializer do not apply an ability check to those records. This issue is fixed in versions 7.4.15, 8.0.15, 8.1.14, and 8.2.6.

Record
CVE-2026-57579
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-862
Updated
2026-11-02
OSV 7.5

Alchemy: Unauthenticated nested page API leaks restricted & unpublished content

Alchemy is an open source content management system engine written in Ruby on Rails. Prior to 7.4.15, 8.0.15, 8.1.14, and 8.2.6, the unauthenticated GET /api/pages/nested endpoint implemented by Api::PagesController#nested in app/controllers/alchemy/api/pages_controller.rb returns an unfiltered page tree because it performs no authorization and does not scope descendants by the caller's ability. Anonymous callers can retrieve restricted and unpublished page metadata that the sibling show action denies. When elements=true is supplied, PageTreeSerializer also returns element and ingredient content from restricted pages because PageTreePreloader and the serializer do not apply an ability check to those records. This issue is fixed in versions 7.4.15, 8.0.15, 8.1.14, and 8.2.6.

Record
CVE-2026-57579
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-862
Updated
2026-11-02
OSVGHSA-mqq5-j7w8-2hgh 7.5

AlchemyCMS: Unauthenticated nested page API leaks restricted & unpublished content

Unauthenticated nested page API leaks restricted & unpublished content

  • Location: app/controllers/alchemy/api/pages_controller.rb:28 (Api::PagesController#nested)
  • Affected version: Alchemy CMS 8.3.0.dev (Rails 8.1.3)

Description

The unauthenticated GET /api/pages/nested endpoint returns the full page tree to any anonymous caller, including restricted (member-only) pages and unpublished/draft pages that should be hidden. Appending ?elements=true additionally dumps the element/ingredient content of restricted pages, fully bypassing the access control the sibling show and index actions enforce.

Root cause

Api::PagesController#nested calls no authorize! and applies no published/restricted scoping, unlike show (authorize! :show) and index (accessible_by(current_ability, :index)). PageTreePreloader loads page.self_and_descendants unfiltered, and PageTreeSerializer emits every page's metadata (and, with elements, public_version.elements) with no ability check.

Evidence

An unauthenticated GET /api/pages/nested returns HTTP 200 with the restricted page ("restricted":true) and an unpublished draft ("public":false); ?elements=true leaks its content (e.g. TOPSECRET_RESTRICTED_BODY_proof123). The same guest hitting GET /api/pages/3 (show) gets HTTP 403 {"error":"Not authorized"}, proving nested returns what show correctly denies.

Reproduction

# 1) Metadata leak (guest, no auth)
curl -s http://localhost:3000/api/pages/nested | python3 -m json.tool | grep -E '"name"|"restricted"|"public"'

# 2) Content leak of restricted page
curl -s "http://localhost:3000/api/pages/nested?elements=true" | grep -oE 'TOPSECRET_RESTRICTED_BODY_[A-Za-z0-9]+|RESTRICTED_RICHTEXT_[A-Za-z0-9]+'

# 3) Contrast — show denies the same guest
curl -s -o /dev/null -w "show /api/pages/3 -> HTTP %{http_code}\n" http://localhost:3000/api/pages/3

Suggested fix

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
  render json: PageTreeSerializer.new(preloaded_page, ability: current_ability,
                                      user: current_alchemy_user, elements: params[:elements])
end

Additionally scope PageTreePreloader's self_and_descendants via accessible_by(current_ability) and gate element emission in PageTreeSerializer#page_elements behind opts[:ability].can?(:show, page).

Record
GHSA-mqq5-j7w8-2hgh
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-862
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
alchemy_cms
RubyGems
8.2.0 to 8.2.5
8.2.6
alchemy_cms
RubyGems
8.1.0 to 8.1.13
8.1.14
alchemy_cms
RubyGems
8.0.0.a to 8.0.14
8.0.15
alchemy_cms
RubyGems
through 7.4.14
7.4.15
alchemy_cms
RubyGems
8.2.0 up to 8.2.6, plus listed versions
8.2.18.2.28.2.38.2.48.2.5
8.2.6
alchemy_cms
RubyGems
8.1.0 up to 8.1.14, plus listed versions
8.1.18.1.108.1.118.1.128.1.13
Show 8 moreShow less
8.1.28.1.38.1.48.1.58.1.68.1.78.1.88.1.9
8.1.14
alchemy_cms
RubyGems
8.0.0.a up to 8.0.15, plus listed versions
8.0.08.0.0.b8.0.0.c8.0.18.0.10
Show 12 moreShow less
8.0.118.0.128.0.138.0.148.0.28.0.38.0.48.0.58.0.68.0.78.0.88.0.9
8.0.15
alchemy_cms
RubyGems
before 7.4.15, plus listed versions
2.02.0.12.0.22.0.32.0.3.1
Show 45 moreShow less
2.0.42.0.52.0.6.12.0.72.0.pre22.0.pre32.0.pre42.0.pre52.0.rc12.0.rc22.0.rc32.0.rc42.0.rc52.0.rc62.12.1.12.1.112.1.122.1.22.1.32.1.42.1.52.1.62.1.72.1.82.1.8.12.1.92.1.9.12.1.beta12.1.beta52.1.beta62.1.rc22.1.rc32.1.rc42.1.rc52.1.rc62.2.02.2.12.2.22.2.3.12.2.3.22.2.42.2.rc12.2.rc112.2.rc13
7.4.15

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-57579 is a high vulnerability (CVSS 7.5) in Alchemycms Alchemy Cms, published June 19, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.65%, the 51st percentile. Fixed in alchemy_cms 8.2.6.

References

Show 9 moreShow less
This page doesn't list everything

Left out here: 293 versions. The JSON record has them.

MoveEnter Open