{"affected":[{"database_specific":{"last_known_affected_version_range":"<= 8.2.5","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-mqq5-j7w8-2hgh/GHSA-mqq5-j7w8-2hgh.json"},"package":{"ecosystem":"RubyGems","name":"alchemy_cms","purl":"pkg:gem/alchemy_cms"},"ranges":[{"events":[{"introduced":"8.2.0"},{"fixed":"8.2.6"}],"type":"ECOSYSTEM"}],"versions":["8.2.0","8.2.1","8.2.2","8.2.3","8.2.4","8.2.5"]},{"database_specific":{"last_known_affected_version_range":"<= 8.1.13","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-mqq5-j7w8-2hgh/GHSA-mqq5-j7w8-2hgh.json"},"package":{"ecosystem":"RubyGems","name":"alchemy_cms","purl":"pkg:gem/alchemy_cms"},"ranges":[{"events":[{"introduced":"8.1.0"},{"fixed":"8.1.14"}],"type":"ECOSYSTEM"}],"versions":["8.1.0","8.1.1","8.1.10","8.1.11","8.1.12","8.1.13","8.1.2","8.1.3","8.1.4","8.1.5","8.1.6","8.1.7","8.1.8","8.1.9"]},{"database_specific":{"last_known_affected_version_range":"<= 8.0.14","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-mqq5-j7w8-2hgh/GHSA-mqq5-j7w8-2hgh.json"},"package":{"ecosystem":"RubyGems","name":"alchemy_cms","purl":"pkg:gem/alchemy_cms"},"ranges":[{"events":[{"introduced":"8.0.0.a"},{"fixed":"8.0.15"}],"type":"ECOSYSTEM"}],"versions":["8.0.0","8.0.0.a","8.0.0.b","8.0.0.c","8.0.1","8.0.10","8.0.11","8.0.12","8.0.13","8.0.14","8.0.2","8.0.3","8.0.4","8.0.5","8.0.6","8.0.7","8.0.8","8.0.9"]},{"database_specific":{"last_known_affected_version_range":"<= 7.4.14","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-mqq5-j7w8-2hgh/GHSA-mqq5-j7w8-2hgh.json"},"package":{"ecosystem":"RubyGems","name":"alchemy_cms","purl":"pkg:gem/alchemy_cms"},"ranges":[{"events":[{"introduced":"0"},{"fixed":"7.4.15"}],"type":"ECOSYSTEM"}],"versions":["2.0","2.0.1","2.0.2","2.0.3","2.0.3.1","2.0.4","2.0.5","2.0.6.1","2.0.7","2.0.pre2","2.0.pre3","2.0.pre4","2.0.pre5","2.0.rc1","2.0.rc2","2.0.rc3","2.0.rc4","2.0.rc5","2.0.rc6","2.1","2.1.1","2.1.11","2.1.12","2.1.2","2.1.3","2.1.4","2.1.5","2.1.6","2.1.7","2.1.8","2.1.8.1","2.1.9","2.1.9.1","2.1.beta1","2.1.beta5","2.1.beta6","2.1.rc2","2.1.rc3","2.1.rc4","2.1.rc5","2.1.rc6","2.2.0","2.2.1","2.2.2","2.2.3.1","2.2.3.2","2.2.4","2.2.rc1","2.2.rc11","2.2.rc13","2.2.rc14","2.2.rc15","2.2.rc2","2.2.rc3","2.2.rc6","2.2.rc7","2.2.rc8","2.3.0","2.3.1","2.3.2","2.3.rc5","2.4.0","2.4.1","2.4.beta2","2.4.rc1","2.4.rc2","2.4.rc4","2.5.0","2.5.0.b2","2.5.0.b5","2.5.0.b9","2.5.0.rc3","2.5.1","2.5.2","2.5.2.1","2.5.2.2","2.5.3","2.5.3.1","2.6.0","2.6.0.rc5","2.6.1","2.6.2","2.6.2.1","2.6.3","2.7.0","2.7.1","2.7.2","2.7.3","2.7.4","2.7.5","2.8.1","2.8.2","2.8.3","2.9.0","2.9.1","3.0.0","3.0.0.rc5","3.0.0.rc6","3.0.0.rc7","3.0.0.rc8","3.0.1","3.0.2","3.0.3","3.0.4","3.1.0","3.1.0.beta1","3.1.0.beta2","3.1.0.beta3","3.1.0.beta4","3.1.0.beta5","3.1.0.beta6","3.1.0.rc1","3.1.0.rc2","3.1.0.rc3","3.1.1","3.1.3","3.2.0","3.2.0.beta","3.2.0.rc1","3.2.1","3.3.0","3.3.0.rc1","3.3.0.rc2","3.3.1","3.3.2","3.3.3","3.4.0","3.4.0.rc1","3.4.1","3.4.2","3.5.0","3.5.0.rc1","3.5.0.rc2","3.6.0","3.6.1","3.6.2","3.6.3","3.6.4","3.6.5","3.6.6","3.6.7","4.0.0","4.0.0.beta","4.0.0.rc1","4.0.0.rc2","4.0.1","4.0.2","4.0.3","4.0.4","4.0.5","4.0.6","4.1.0","4.1.0.beta","4.1.0.rc1","4.1.1","4.1.2","4.2.0","4.2.0.rc1","4.2.1","4.2.2","4.2.3","4.2.4","4.3.0","4.3.1","4.3.2","4.4.0","4.4.1","4.4.2","4.4.3","4.4.4","4.4.5","4.5.0","4.5.1","4.6.0","4.6.1","4.6.2","4.6.3","4.6.4","4.6.5","4.6.6","4.6.7","5.0.0","5.0.0.beta1","5.0.0.beta2","5.0.0.rc1","5.0.0.rc2","5.0.1","5.0.10","5.0.2","5.0.3","5.0.4","5.0.5","5.0.6","5.0.7","5.0.8","5.0.9","5.1.0","5.1.0.beta1","5.1.0.beta2","5.1.0.rc1","5.1.1","5.1.10","5.1.2","5.1.3","5.1.4","5.1.5","5.1.6","5.1.7","5.1.8","5.1.9","5.2.0","5.2.0.b1","5.2.0.rc1","5.2.1","5.2.2","5.2.3","5.2.4","5.2.5","5.2.6","5.2.7","5.3.0","5.3.1","5.3.2","5.3.3","5.3.4","5.3.5","5.3.6","5.3.7","5.3.8","6.0.0","6.0.0.b1","6.0.0.b2","6.0.0.b3","6.0.0.pre.b4","6.0.0.pre.b5","6.0.0.pre.b6","6.0.0.pre.rc1","6.0.0.pre.rc2","6.0.0.pre.rc3","6.0.0.pre.rc4","6.0.0.pre.rc5","6.0.0.pre.rc6","6.0.0.pre.rc7","6.0.1","6.0.10","6.0.11","6.0.12","6.0.13","6.0.14","6.0.2","6.0.3","6.0.4","6.0.5","6.0.6","6.0.7","6.0.8","6.0.9","6.1.0","6.1.1","6.1.10","6.1.2","6.1.3","6.1.4","6.1.5","6.1.6","6.1.7","6.1.8","6.1.9","7.0.0","7.0.0.pre.a","7.0.0.pre.b","7.0.0.pre.c","7.0.0.pre.rc1","7.0.1","7.0.10","7.0.11","7.0.12","7.0.13","7.0.14","7.0.15","7.0.16","7.0.2","7.0.3","7.0.4","7.0.5","7.0.6","7.0.7","7.0.8","7.0.9","7.1.0","7.1.0.pre.b1","7.1.0.pre.b2","7.1.0.pre.rc1","7.1.1","7.1.10","7.1.11","7.1.12","7.1.13","7.1.2","7.1.3","7.1.4","7.1.5","7.1.6","7.1.7","7.1.8","7.1.9","7.2.0","7.2.0.b","7.2.0.rc1","7.2.0.rc2","7.2.1","7.2.2","7.2.3","7.2.4","7.2.5","7.2.6","7.2.7","7.2.8","7.2.9","7.3.0","7.3.1","7.3.2","7.3.3","7.3.4","7.3.5","7.3.6","7.3.7","7.3.8","7.4.0","7.4.1","7.4.10","7.4.11","7.4.12","7.4.13","7.4.14","7.4.2","7.4.3","7.4.4","7.4.5","7.4.6","7.4.7","7.4.8","7.4.9"]}],"aliases":["CVE-2026-57579"],"database_specific":{"cwe_ids":["CWE-862"],"github_reviewed":true,"github_reviewed_at":"2026-06-19T17:47:13Z","nvd_published_at":null,"severity":"HIGH"},"details":"# Unauthenticated nested page API leaks restricted & unpublished content\n\n- **Location:** `app/controllers/alchemy/api/pages_controller.rb:28` (`Api::PagesController#nested`)\n- **Affected version:** Alchemy CMS 8.3.0.dev (Rails 8.1.3)\n\n## Description\n\nThe 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.\nAppending `?elements=true` additionally dumps the element/ingredient **content** of restricted pages, fully bypassing the access control the sibling `show` and `index` actions enforce.\n\n## Root cause\n\n`Api::PagesController#nested` calls no `authorize!` and applies no `published`/`restricted` scoping, unlike `show` (`authorize! :show`) and `index` (`accessible_by(current_ability, :index)`).\n`PageTreePreloader` loads `page.self_and_descendants` unfiltered, and `PageTreeSerializer` emits every page's metadata (and, with `elements`, `public_version.elements`) with no ability check.\n\n## Evidence\n\nAn 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`).\nThe same guest hitting `GET /api/pages/3` (`show`) gets HTTP **403** `{\"error\":\"Not authorized\"}`, proving `nested` returns what `show` correctly denies.\n\n### Reproduction\n\n```bash\n# 1) Metadata leak (guest, no auth)\ncurl -s http://localhost:3000/api/pages/nested | python3 -m json.tool | grep -E '\"name\"|\"restricted\"|\"public\"'\n\n# 2) Content leak of restricted page\ncurl -s \"http://localhost:3000/api/pages/nested?elements=true\" | grep -oE 'TOPSECRET_RESTRICTED_BODY_[A-Za-z0-9]+|RESTRICTED_RICHTEXT_[A-Za-z0-9]+'\n\n# 3) Contrast — show denies the same guest\ncurl -s -o /dev/null -w \"show /api/pages/3 -> HTTP %{http_code}\\n\" http://localhost:3000/api/pages/3\n```\n\n### Suggested fix\n\n```ruby\ndef nested\n  @page = Page.find_by(id: params[:page_id]) || Language.current_root_page\n  authorize! :show, @page\n  preloaded_page = PageTreePreloader.new(page: @page, user: current_alchemy_user, ability: current_ability).call\n  render json: PageTreeSerializer.new(preloaded_page, ability: current_ability,\n                                      user: current_alchemy_user, elements: params[:elements])\nend\n```\n\nAdditionally 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)`.","id":"GHSA-mqq5-j7w8-2hgh","modified":"2026-09-15T03:56:01.761610104Z","published":"2026-06-19T17:47:13Z","references":[{"type":"WEB","url":"https://github.com/AlchemyCMS/alchemy_cms/security/advisories/GHSA-mqq5-j7w8-2hgh"},{"type":"PACKAGE","url":"https://github.com/AlchemyCMS/alchemy_cms"}],"schema_version":"1.9.0","severity":[{"score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","type":"CVSS_V3"}],"summary":"AlchemyCMS: Unauthenticated nested page API leaks restricted & unpublished content"}