<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title type="text"><![CDATA[RubySec]]></title>
  <subtitle type="text"><![CDATA[Providing security resources for the Ruby community]]></subtitle>
  <link href="https://rubysec.com/atom.xml" rel="self"/>
  <link href="https://rubysec.com/" rel="alternate" hreflang="en" />
  <updated>2026-07-14T16:24:55+00:00</updated>
  <id>https://rubysec.com/</id>
  <author>
    <name><![CDATA[RubySec]]></name>
    
  </author>
  <generator uri="https://jekyllrb.com/">Jekyll</generator>

  
  <entry>
    <title type="html"><![CDATA[CVE-2026-38969 (webrick): ruby webrick through v1.9.2 WEBrick reparses trailer]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/CVE-2026-38969/"/>
    <id>https://rubysec.com/advisories/CVE-2026-38969</id>
    <updated>2026-07-02T00:00:00+00:00</updated>
    <content type="html"><![CDATA[ruby webrick through v1.9.2 WEBrick reparses trailer Content-Length
into canonical request state, enabling request smuggling.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[GHSA-mjgf-xj26-9qf9 (pay): pay-rails/pay - non-constant-time HMAC comparison in Paddle Billing webhook signature verifier]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/GHSA-mjgf-xj26-9qf9/"/>
    <id>https://rubysec.com/advisories/GHSA-mjgf-xj26-9qf9</id>
    <updated>2026-07-01T00:00:00+00:00</updated>
    <content type="html"><![CDATA[## Summary

The `Pay::Webhooks::PaddleBillingController#valid_signature?`
(`app/controllers/pay/webhooks/paddle_billing_controller.rb`)
verifies the Paddle Billing webhook signature by computing
`OpenSSL::HMAC.hexdigest(...)` and comparing it to the attacker-supplied
header value using Ruby's `String#==`. Ruby's `==` is non-constant-time —
it returns as soon as the first byte mismatches — and exposes a per-byte
timing side channel on the webhook signature verification path. The
canonical mitigation is to use a constant-time primitive
(`OpenSSL.fixed_length_secure_compare` /
`ActiveSupport::SecurityUtils.secure_compare`).

- IMPACT - CWE-208 — Observable Timing Discrepancy on the  webhook
  signature verifier.
  - An attacker who can deliver requests to the `/pay/webhooks/paddle_billing`
    mount point can probe the verifier with guessed `Paddle-Signature`
    header values. Because `String#==` short-circuits on the first
    mismatching byte, the response-time distribution shifts as the prefix
    of the guess matches the real hex digest.
  - A signature recovered through the oracle lets the attacker deliver
    forged Paddle Billing webhook events (e.g. `subscription.created` /
    `transaction.completed`) against the host application. Pay's webhook
    'processor enqueues a `Pay::Webhooks::ProcessJob` for any accepted'
    webhook, which downstream applications use to update billing state —
    including provisioning paid features, recording refunds, and
    triggering customer notifications.
  - The endpoint is internet-reachable by definition (Paddle must
    POST events to it).

- Credit - Reported by tonghuaroot (https://github.com/tonghuaroot)]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[CVE-2026-54696 (json): JSON generator heap buffer overflow when streaming to an IO]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/CVE-2026-54696/"/>
    <id>https://rubysec.com/advisories/CVE-2026-54696</id>
    <updated>2026-06-30T00:00:00+00:00</updated>
    <content type="html"><![CDATA[Ruby JSON is a JSON implementation for Ruby. Versions 2.9.0 through
2.19.8 are vulnerable to heap buffer overflow when the JSON generator
is provided with an oversized streamed object.

When streaming to an IO JSON.dump(obj, io) and JSON::State#generate(obj, io)
can write past the internal JSON generator buffer when a streamed
object contains an attacker-controlled string near 16 KB. Exploitation
would result in a reliable process crash/denial of service.

This was triaged on HackerOne as report #3785370.
The issue was confirmed there and I was asked to open it here.

This issue has been fixed in version 2.19.9.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[CVE-2026-44161 (fluentd): Fluentd is Vulnerable to Server-Side Request Forgery (SSRF) via Placeholder Expansion in `out_http`]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/CVE-2026-44161/"/>
    <id>https://rubysec.com/advisories/CVE-2026-44161</id>
    <updated>2026-06-26T00:00:00+00:00</updated>
    <content type="html"><![CDATA[The `out_http` output plugin allows the use of placeholders (such as
`${tag}`) in the `endpoint` configuration parameter. It was discovered
that if the placeholder value is derived from untrusted user input,
an attacker can maliciously control the destination hostname of the
outbound HTTP requests made by Fluentd.

## Impact

This vulnerability allows for a **Server-Side Request Forgery (SSRF)**
attack. An unauthenticated attacker can force the Fluentd node to send
HTTP requests to arbitrary internal services. This can lead to
unauthorized access to internal APIs, data exfiltration, or the
compromise of cloud metadata endpoints (e.g., AWS IMDS `169.254.169.254`).]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[CVE-2026-44160 (fluentd): Fluentd is Vulnerable to Denial of Service (DoS) via Gzip Decompression Bomb in `in_http` and `in_forward`]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/CVE-2026-44160/"/>
    <id>https://rubysec.com/advisories/CVE-2026-44160</id>
    <updated>2026-06-26T00:00:00+00:00</updated>
    <content type="html"><![CDATA[Fluentd's `in_http` and `in_forward` plugins support receiving
gzip-compressed data.

While Fluentd correctly enforces size limits on the incoming
compressed payloads (e.g., via `body_size_limit` or `chunk_size_limit`),
it was discovered that there is no limit enforced on the size of the
decompressed data. If a Fluentd instance is exposed to untrusted
networks, an attacker can send a maliciously crafted, highly
compressed payload. When Fluentd attempts to decompress this payload
in memory, it will expand to an excessive size, completely bypassing
the intended payload size limits.

### Impact

This vulnerability allows for a **Denial of Service (DoS)** attack
via memory exhaustion. The rapid memory consumption during decompression
can easily lead to an Out-of-Memory kill of the Fluentd process by
the operating  system. This results in the disruption of all log
collection and forwarding capabilities on the affected node.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[CVE-2026-44025 (fluentd): Fluentd is Vulnerable to Exposure of Sensitive Information via Monitor Agent API]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/CVE-2026-44025/"/>
    <id>https://rubysec.com/advisories/CVE-2026-44025</id>
    <updated>2026-06-26T00:00:00+00:00</updated>
    <content type="html"><![CDATA[Fluentd's Monitor Agent plugin (`in_monitor_agent`) exposes internal
metrics and plugin information via a REST API.
It was discovered that the API response (`/api/plugins.json` and
related endpoints) unintentionally includes internal instance
variables of loaded plugins.

If any plugins store sensitive information—such as database passwords,
API keys, or cloud credentials—in its instance variables, this
information may be exposed in plain text to any user or system
that has HTTP access to the Monitor Agent API.

### Impact

This vulnerability allows for unauthorized information disclosure. An
attacker who can reach the Monitor Agent API port (default: `24220`)
can potentially extract sensitive credentials used by other Fluentd plugins.
The impact severity depends highly on the network configuration (whether
the Monitor Agent port is exposed to untrusted networks) and the
specific plugins configured in the Fluentd instance.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[CVE-2026-44024 (fluentd): Fluentd is Vulnerable to Remote Code Execution (RCE) via Arbitrary File Write in `${tag}` Placeholder]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/CVE-2026-44024/"/>
    <id>https://rubysec.com/advisories/CVE-2026-44024</id>
    <updated>2026-06-26T00:00:00+00:00</updated>
    <content type="html"><![CDATA[Fluentd allows dynamically constructing file paths using the `${tag}`
placeholder. It was discovered that validation for this placeholder
was insufficient.

If a Fluentd instance is configured to receive logs from untrusted
sources and uses the `${tag}` placeholder in file configurations
(such as the `path` parameter in the `out_file` plugin), an attacker
can inject path traversal characters (e.g., `../`).

When combined with certain formatting options, this vulnerability allows
an attacker to write arbitrary files or overwrite existing files on
the system with attacker-controlled content, bypassing intended
directory restrictions.

### Impact

This vulnerability allows for **Arbitrary File Write**, which can be
directly escalated to full **Remote Code Execution (RCE)**.
An attacker could achieve RCE by overwriting critical system files,
injecting executable plugins, or modifying configuration files.
The impact is Critical as it can lead to full system compromise without
any authentication, depending on the Fluentd configuration and the
privileges of the Fluentd process.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[GHSA-wwpr-jff3-395c (crass): A large number of adjacent CSS comments can trigger a SystemStackError]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/GHSA-wwpr-jff3-395c/"/>
    <id>https://rubysec.com/advisories/GHSA-wwpr-jff3-395c</id>
    <updated>2026-06-25T00:00:00+00:00</updated>
    <content type="html"><![CDATA[## Impact

When the :preserve_comments option is not enabled (which is the
default behavior), Crass discards CSS comments by recursively
consuming the next token. An attacker who provides a stylesheet
containing a very large number of adjacent comments can cause
excessive recursion and trigger a SystemStackError.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[GHSA-8vfg-2r28-hvhj (crass): Non-ASCII characters cause superlinear CPU consumption]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/GHSA-8vfg-2r28-hvhj/"/>
    <id>https://rubysec.com/advisories/GHSA-8vfg-2r28-hvhj</id>
    <updated>2026-06-25T00:00:00+00:00</updated>
    <content type="html"><![CDATA[## Impact

When parsing an input containing non-ASCII characters, inefficiencies
in how Crass tracks the positions of multi-byte characters result
in superlinear parsing time. An attacker-controlled input consisting
of many non-ASCII characters could cause excessive CPU consumption
and potentially denial of service.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[GHSA-6wmf-3r64-vcwv (crass): Large numeric exponents cause CPU and memory denial of service]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/GHSA-6wmf-3r64-vcwv/"/>
    <id>https://rubysec.com/advisories/GHSA-6wmf-3r64-vcwv</id>
    <updated>2026-06-25T00:00:00+00:00</updated>
    <content type="html"><![CDATA[## Impact

Crass converts CSS scientific notation number values with unbounded
exponentiation before it clamps the result to Float::MAX. Applications
that use Crass to parse attacker-controlled CSS strings can be forced
to spend disproportionate CPU and memory parsing a tiny input,
possibly resulting in a crash.

Exponents are now bounded before 10**exponent is computed.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[GHSA-6jxj-px6v-747w (crass): Deeply nested CSS blocks and functions can trigger a SystemStackError or excessive memory usage]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/GHSA-6jxj-px6v-747w/"/>
    <id>https://rubysec.com/advisories/GHSA-6jxj-px6v-747w</id>
    <updated>2026-06-25T00:00:00+00:00</updated>
    <content type="html"><![CDATA[## Impact

Crass recursively parses CSS simple blocks and functions without a
depth guard. An attacker-controlled value containing many deeply
nested blocks can recurse until Ruby raises SystemStackError:
stack level too deep, or can cause excessive memory usage.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[CVE-2026-44163 (fluent-plugin-opentelemetry): fluent-plugin-opentelemetry Has Denial of Service (DoS) via Large Payloads and Decompression Bombs in `in_opentelemetry`]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/CVE-2026-44163/"/>
    <id>https://rubysec.com/advisories/CVE-2026-44163</id>
    <updated>2026-06-25T00:00:00+00:00</updated>
    <content type="html"><![CDATA[The `fluent-plugin-opentelemetry` plugin (specifically the
`in_opentelemetry` HTTP input) lacked strict size limits on incoming
requests. It was discovered that the plugin read the entire request
body and decompressed payloads into memory without enforcing maximum
size thresholds. If the OpenTelemetry ingestion endpoint is exposed to
untrusted networks, an attacker can send an excessively large HTTP
request  or a maliciously crafted, highly compressed payload.
When the plugin attempts to read or decompress this payload, it will
expand to an excessive size and it will consume significant system resources.

### Impact

This vulnerability allows for a **Denial of Service (DoS)** attack
via memory exhaustion. The rapid memory consumption during decompression
can easily lead to an Out-of-Memory kill of the Fluentd process by the
operating system. This results in the disruption of all log collection
and forwarding capabilities on the affected node.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[CVE-2026-44162 (fluent-plugin-s3): fluent-plugin-s3 Vulnerable to Denial of Service (DoS) via Decompression Bomb in `in_s3`]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/CVE-2026-44162/"/>
    <id>https://rubysec.com/advisories/CVE-2026-44162</id>
    <updated>2026-06-25T00:00:00+00:00</updated>
    <content type="html"><![CDATA["The `fluent-plugin-s3` plugin (specifically the `in_s3` input plugin)
supports reading and decompressing heavily compressed files (such as
`gzip`, `lzma2`, and `lzop`) from Amazon S3. It was discovered that
the plugin read the entire decompressed payload into memory at once
without enforcing a strict size limit.

If an attacker has sufficient permissions to upload files to the
monitored S3 bucket, they can upload a maliciously crafted, highly
compressed file. When Fluentd attempts to decompress this file, it
will expand to an excessive size and it will consume significant
system resources.

## Impact

This vulnerability allows for a **Denial of Service (DoS)** attack
via memory exhaustion. The rapid memory consumption during decompression
can lead to an Out-of-Memory kill of the Fluentd process by the
operating system, This results in the disruption of all log collection
on the affected node.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[GHSA-2x63-gw47-w4mm (websocket-driver): Denial of service via malformed Host header]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/GHSA-2x63-gw47-w4mm/"/>
    <id>https://rubysec.com/advisories/GHSA-2x63-gw47-w4mm</id>
    <updated>2026-06-23T00:00:00+00:00</updated>
    <content type="html"><![CDATA[## Impact

If this library is used to implement a WebSocket server on top of a
TCP server, by using the WebSocket::Driver.server() method, then a
client can cause the server to crash by sending a Host header that
is not a valid host[:port] string. When this happens, a URI::InvalidURIError
exception is raised which is not caught, and this can cause the server
process to crash if the application does not catch the error from
 the parse() method itself.

## Acknowledgements

This issue was discovered and reported by Pranjali Thakur,
DepthFirst Security Research Team.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[CVE-2026-49342 (yard): YARD static cache reads raw traversal paths before router sanitization]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/CVE-2026-49342/"/>
    <id>https://rubysec.com/advisories/CVE-2026-49342</id>
    <updated>2026-06-23T00:00:00+00:00</updated>
    <content type="html"><![CDATA[## Summary

YARD's static cache lookup reads a request path before the router's
path cleanup runs. When a server is configured with a document root,
a traversal path such as `/../yard-cache-secret.html` is joined
against that root and can return a readable sibling `.html` file
outside the intended static tree.

The potential security risk seems low, as only html-ending files can
be read, but still the risk of reading arbitrary html files is a
confiendtiality issue in itself, which is why we decided to report.
Please let us know if this is out of your project's scope.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[GHSA-wjv4-x9w8-wm3h (nokogiri): Nokogiri: Possible Use-After-Free when setting `Document#root=` to an invalid node type]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/GHSA-wjv4-x9w8-wm3h/"/>
    <id>https://rubysec.com/advisories/GHSA-wjv4-x9w8-wm3h</id>
    <updated>2026-06-19T00:00:00+00:00</updated>
    <content type="html"><![CDATA[### Summary

`Nokogiri::XML::Document#root=` validated only that the new root was a
`Nokogiri::XML::Node`, allowing a DTD node to be set as the document root. The
result is a heap use-after-free during garbage collection or finalization,
leading to an invalid memory read or potentially a segfault.

Nokogiri 1.19.4 restricts `Document#root=` to element nodes, raising
`TypeError` for any other node type.

This memory-safety issue affects only the CRuby implementation (libxml2). The
JRuby implementation was not affected; the same input validation was added
there for behavioral parity.

### Severity

The Nokogiri maintainers have evaluated this as low severity. This is only
triggered by a programming error. It requires application code to assign a
non-element node such as a DTD as the document root via `Document#root=`.
Nokogiri 1.19.4 now raises `TypeError` instead of allowing a use-after-free.
It cannot be triggered by untrusted input or through normal use of the public
API.

### Mitigation

Upgrade to Nokogiri 1.19.4 or later.

As a workaround, applications that cannot upgrade should avoid assigning a DTD
(or any non-element node) via `Document#root=`.

### Credit

This issue was responsibly reported by Zheng Yu from depthfirst.com.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[GHSA-wfpw-mmfh-qq69 (nokogiri): Nokogiri: Possible Use-After-Free in XInclude Processing]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/GHSA-wfpw-mmfh-qq69/"/>
    <id>https://rubysec.com/advisories/GHSA-wfpw-mmfh-qq69</id>
    <updated>2026-06-19T00:00:00+00:00</updated>
    <content type="html"><![CDATA[### Summary

XInclude substitution performed by `Nokogiri::XML::Node#do_xinclude` replaced
each `<xi:include>` in place, freeing the include node along with its children
(such as `<xi:fallback>` and its descendants) and any namespaces declared on
them. If an application had already exposed one of those nodes or namespaces
to Ruby, the corresponding Ruby object was left pointing at freed memory.
Using the object could result in invalid reads or writes to memory.

Nokogiri 1.19.4 substitutes each `<xi:include>` on a defensive copy by
default, so the structures libxml2 frees are never the ones bound to live Ruby
objects.

Only the CRuby implementation is affected; JRuby is not affected.

### Severity

The Nokogiri maintainers have evaluated this as low severity. Reaching it
requires an unusual API-usage pattern that does not arise during normal use.
The application must parse a document without XInclude, traverse into an
`<xi:include>` subtree to expose its nodes or namespaces to Ruby, and only
then invoke XInclude processing. The common case, requesting XInclude at parse
time, operates on a freshly parsed document whose nodes are not yet exposed to
Ruby and is not affected. Nokogiri 1.19.4 makes this pattern safe by default
and requires no change to application code.

### Mitigation

Upgrade to Nokogiri 1.19.4 or later.

As a workaround for earlier versions, perform XInclude substitution at parse
time (with the `xinclude` parse option) rather than calling `#do_xinclude` on
a document that has already been traversed. A freshly parsed document has no
nodes exposed to Ruby, so the substitution is safe.

### Credit

This issue was responsibly reported by Zheng Yu from depthfirst.com.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[GHSA-phwj-rprq-35pp (nokogiri): Nokogiri: Possible Use-After-Free when setting an attribute value via `Nokogiri::XML::Attr#value=` or `#content=`]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/GHSA-phwj-rprq-35pp/"/>
    <id>https://rubysec.com/advisories/GHSA-phwj-rprq-35pp</id>
    <updated>2026-06-19T00:00:00+00:00</updated>
    <content type="html"><![CDATA[### Summary

Nokogiri's CRuby native extension could leave a Ruby wrapper pointing to freed
memory when replacing the value of an XML attribute. If Ruby code had already
accessed an attribute child node, `Nokogiri::XML::Attr#value=` could free the
underlying native child node while the wrapper remained reachable through the
document node cache. A later use of the freed child node or a Ruby GC mark
could dereference an invalid pointer, causing an invalid read and a possible
segfault.

Nokogiri 1.19.4 preserves any already-wrapped attribute child nodes before
replacing the attribute value.

JRuby is not affected.

### Severity

The Nokogiri maintainers have evaluated this as low severity. Reaching it
requires an unusual API-usage pattern that does not arise during normal use.
The application must directly access an attribute's child node and then
replace that same attribute's value via `Attr#value=` or `#content=`. Nokogiri
1.19.4 makes this pattern safe with no change to the public API.
Already-wrapped attribute child nodes are preserved before the value is
replaced.

### Mitigation

Upgrade to Nokogiri 1.19.4 or later.

As a workaround, avoid accessing attribute child nodes directly via
`Attr#child` or similar before mutating the same attribute’s value.

### Credit

This issue was responsibly reported by Zheng Yu from depthfirst.com.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[GHSA-p67v-3w7g-wjg7 (nokogiri): Nokogiri: Possible Use-After-Free when directly using `NokogirI::XML::XPathContext` beyond document lifetime]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/GHSA-p67v-3w7g-wjg7/"/>
    <id>https://rubysec.com/advisories/GHSA-p67v-3w7g-wjg7</id>
    <updated>2026-06-19T00:00:00+00:00</updated>
    <content type="html"><![CDATA[### Summary

`Nokogiri::XML::XPathContext` did not keep its source document alive for
garbage collection. If an `XPathContext` outlived its document and the
document was collected, evaluating an XPath expression could read invalid
memory and potentially segfault.

This is only reachable when application code constructs an `XPathContext`
directly and lets the document become unreachable while continuing to use the
context. The normal `Document#xpath`, `#css`, and related search methods are
not affected, and it is not triggerable by malicious document input.

Nokogiri 1.19.4 makes `XPathContext` keep its source document alive for as
long as the context exists.

Only the CRuby implementation is affected. JRuby is not affected.

### Severity

The Nokogiri maintainers have evaluated this as low severity. Reaching it
requires an unusual API-usage pattern that does not arise during normal use.
The application must construct an `XML::XPathContext` directly and continue
using it after allowing its source document to be garbage-collected. Nokogiri
1.19.4 makes this pattern safe with no change to the public API. The context
now keeps its source document alive for as long as it exists.

### Mitigation

Upgrade to Nokogiri 1.19.4 or later.

As a workaround, ensure the source document remains referenced for as long as
any `XPathContext` created from it is in use. The standard `Document#xpath`,
`#css`, and related search methods already do this and are unaffected.

### Credit

This issue was responsibly reported by Zheng Yu from depthfirst.com.]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[GHSA-mqq5-j7w8-2hgh (alchemy_cms): AlchemyCMS - Unauthenticated nested page API leaks restricted and unpublished content]]></title>
    <link rel="alternate" href="https://rubysec.com/advisories/GHSA-mqq5-j7w8-2hgh/"/>
    <id>https://rubysec.com/advisories/GHSA-mqq5-j7w8-2hgh</id>
    <updated>2026-06-19T00:00:00+00:00</updated>
    <content type="html"><![CDATA[# 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.]]></content>
  </entry>
  
</feed>
