<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="/static/style.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <id>https://vulnerability.circl.lu/rss/recent/all/10</id>
  <title>Most recent entries from all</title>
  <updated>2026-09-30T17:50:05.679999+00:00</updated>
  <author>
    <name>Vulnerability-Lookup</name>
    <email>info@circl.lu</email>
  </author>
  <link href="https://vulnerability.circl.lu" rel="alternate"/>
  <generator uri="https://lkiesow.github.io/python-feedgen" version="1.0.0">python-feedgen</generator>
  <subtitle>Contains only the most 10 recent entries.</subtitle>
  <entry>
    <id>https://vulnerability.circl.lu/vuln/ghsa-x2f5-4prf-w687</id>
    <title>GHSA-x2f5-4prf-w687 — Ruby json: JSON generator heap buffer overflow when streaming to an IO</title>
    <updated>2026-09-30T17:50:05.681490+00:00</updated>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p><strong>Affected:</strong> RubyGems: json</p>
<p>### Summary</p>
<p>`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. The issue is a heap out-of-bounds write
in the IO-streaming path and is demonstrated as a reliable process crash /
denial of service.</p>
<p>This was triaged on HackerOne as report #3785370. The issue was confirmed there
and I was asked to open it here.</p>
<p>### Details</p>
<p>Root cause is in `ext/json/fbuffer/fbuffer.h`, `fbuffer_do_inc_capa()`.</p>
<p>On the IO path, the buffer is grown to `FBUFFER_IO_BUFFER_SIZE` (16383), but the
early return checks total capacity instead of remaining capacity:</p>
<p>```c
if (RB_UNLIKELY(fb-&gt;io)) {
    if (fb-&gt;capa &lt; FBUFFER_IO_BUFFER_SIZE) {
        fbuffer_realloc(fb, FBUFFER_IO_BUFFER_SIZE);
    } else {
        fbuffer_flush(fb);
    }</p>
<p>if (RB_LIKELY(requested &lt; fb-&gt;capa)) {
        return;
    }
}
```</p>
<p>If `fb-&gt;len` already contains JSON syntax bytes, and a string flush has
`16383 - fb-&gt;len &lt;= requested &lt; 16383`, this check returns even though there is
not enough space left. `fbuffer_append_reserved()` then writes past the buffer:</p>
<p>```c
MEMCPY(fb-&gt;ptr + fb-&gt;len, newstr, char, len);
```</p>
<p>The minimal fix is to compare against the remaining capacity:</p>
<p>```diff
-        if (RB_LIKELY(requested &lt; fb-&gt;capa)) {
+        if (RB_LIKELY(requested &lt;= fb-&gt;capa - fb-&gt;len)) {
             return;
         }
```</p>
<p>### PoC</p>
<p>```ruby
require "json"
require "stringio"</p>
<p>io = StringIO.new…</p></div>
    </content>
    <link href="https://vulnerability.circl.lu/vuln/ghsa-x2f5-4prf-w687"/>
  </entry>
</feed>
