Skip to content

Commit 960b055

Browse files
authored
Merge pull request #1257 from petergoldstein/dalli-2026-10-security
Six new dalli advisories
2 parents b238581 + bf33195 commit 960b055

6 files changed

Lines changed: 329 additions & 0 deletions

‎gems/dalli/GHSA-3553-vcg5-72jw.yml‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
gem: dalli
3+
ghsa: 3553-vcg5-72jw
4+
url: https://github.com/petergoldstein/dalli/security/advisories/GHSA-3553-vcg5-72jw
5+
title: Unbounded decompression and reply sizes allow memory exhaustion
6+
date: 2026-10-05
7+
description: |
8+
1. Values flagged as compressed were inflated with no size limit. A
9+
~130 KB stored item expands to 128 MB on read (about 1000:1),
10+
regardless of the client's `compress` or `serializer` settings.
11+
2. The size in a reply (a meta `VA <size>`, or a binary body length) was
12+
used to read or buffer that many bytes, so a hostile or compromised
13+
server could make the client allocate gigabytes.
14+
15+
Exploiting either requires write access to the memcached instance (a
16+
shared or exposed instance, another tenant), or a malicious server or
17+
proxy. Patched versions add a `decompressed_max_bytes` option (default
18+
128 MiB) and reject reply sizes over 1 GiB.
19+
patched_versions:
20+
- "~> 3.2.12"
21+
- "~> 4.3.6"
22+
- "~> 5.0.9"
23+
- "~> 5.1.3"
24+
- ">= 5.2.1"
25+
related:
26+
url:
27+
- https://github.com/petergoldstein/dalli/security/advisories/GHSA-3553-vcg5-72jw
28+
- https://github.com/petergoldstein/dalli/commit/39d2f72
29+
- https://rubygems.org/gems/dalli/versions/5.2.1
30+
- https://github.com/petergoldstein/dalli/releases/tag/v5.2.1
31+
- https://rubygems.org/gems/dalli/versions/5.1.3
32+
- https://github.com/petergoldstein/dalli/releases/tag/v5.1.3
33+
- https://rubygems.org/gems/dalli/versions/5.0.9
34+
- https://github.com/petergoldstein/dalli/releases/tag/v5.0.9
35+
- https://rubygems.org/gems/dalli/versions/4.3.6
36+
- https://github.com/petergoldstein/dalli/releases/tag/v4.3.6
37+
- https://rubygems.org/gems/dalli/versions/3.2.12
38+
- https://github.com/petergoldstein/dalli/releases/tag/v3.2.12
39+
notes: |
40+
- No CVE in GHSA.
41+
- "A CVE has been requested through GitHub but not yet
42+
assigned, so the entry has no cve: field."
43+
- No CVSS score in GHSA; GitHub severity is medium.

‎gems/dalli/GHSA-4qp6-2jcr-596v.yml‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
gem: dalli
3+
ghsa: 4qp6-2jcr-596v
4+
url: https://github.com/petergoldstein/dalli/security/advisories/GHSA-4qp6-2jcr-596v
5+
title: Routing tokens can inject meta protocol flags, and failed requests can
6+
retry forever
7+
date: 2026-10-05
8+
description: |
9+
1. `p_token` and `l_token` were checked only for CR, LF and NUL. A token
10+
containing spaces added arbitrary meta flags to the command: for
11+
example changing an item's TTL on a read, creating stub items on a
12+
miss, turning a delete into a stale tombstone, choosing `incr`'s
13+
initial value, or reading a different key. Affects 5.1.0 and later.
14+
2. Failed requests were retried without a limit. Each retry reconnected
15+
successfully, which reset the failure count, so `socket_max_failures`
16+
was never reached and requests to a server that accepts connections
17+
but never replies (or drops the connection on a request) hung
18+
forever. Affects all versions.
19+
3. Errors raised by application code inside a `get_multi` block
20+
(`Errno::*`, `Timeout::Error`) were treated as socket errors and
21+
retried the whole `get_multi`, causing duplicate yields, swallowed
22+
exceptions, or an endless loop. Affects 4.x and 5.x.
23+
24+
### Workarounds
25+
26+
Don't pass untrusted input as a routing token.
27+
patched_versions:
28+
- "~> 3.2.12"
29+
- "~> 4.3.6"
30+
- "~> 5.0.9"
31+
- "~> 5.1.3"
32+
- ">= 5.2.1"
33+
related:
34+
url:
35+
- https://github.com/petergoldstein/dalli/security/advisories/GHSA-4qp6-2jcr-596v
36+
- https://github.com/petergoldstein/dalli/commit/f8f7a21
37+
- https://rubygems.org/gems/dalli/versions/5.2.1
38+
- https://github.com/petergoldstein/dalli/releases/tag/v5.2.1
39+
- https://rubygems.org/gems/dalli/versions/5.1.3
40+
- https://github.com/petergoldstein/dalli/releases/tag/v5.1.3
41+
- https://rubygems.org/gems/dalli/versions/5.0.9
42+
- https://github.com/petergoldstein/dalli/releases/tag/v5.0.9
43+
- https://rubygems.org/gems/dalli/versions/4.3.6
44+
- https://github.com/petergoldstein/dalli/releases/tag/v4.3.6
45+
- https://rubygems.org/gems/dalli/versions/3.2.12
46+
- https://github.com/petergoldstein/dalli/releases/tag/v3.2.12
47+
notes: |
48+
- No CVE in GHSA.
49+
- "A CVE has been requested through GitHub but not yet
50+
assigned, so the entry has no cve: field."
51+
- No CVSS score in GHSA; GitHub severity is medium.

‎gems/dalli/GHSA-m252-9cgf-vx2w.yml‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
gem: dalli
3+
ghsa: m252-9cgf-vx2w
4+
url: https://github.com/petergoldstein/dalli/security/advisories/GHSA-m252-9cgf-vx2w
5+
title: With a namespace, a retried request reads or writes a different key
6+
date: 2026-10-05
7+
description: |
8+
When a client is configured with a `namespace`, a request that hits a
9+
transient network error (a timeout, or a connection closed by memcached
10+
or a proxy, such as stale connections after a memcached restart) was
11+
retried with the namespace applied a second time, so `app:x` became
12+
`app:app:x`. A retried read could return a different key's value, and a
13+
retried write could overwrite a different key. Where cache keys include
14+
user input, a user who can choose a key of the form `app:<something>`
15+
can arrange for another user's retried read to return attacker-chosen
16+
data.
17+
18+
Affected: every single-key operation since 5.0.3, single-server
19+
`get_multi` since 5.1.0, and `get_with_metadata` and `fetch_with_lock`
20+
since 4.1.0. Clients without a namespace are not affected, and 3.2.x is
21+
not affected.
22+
23+
### Workarounds
24+
25+
Don't configure a `namespace`; prefix keys in application code instead.
26+
unaffected_versions:
27+
- "< 4.1.0"
28+
patched_versions:
29+
- "~> 4.3.7"
30+
- "~> 5.0.10"
31+
- "~> 5.1.4"
32+
- ">= 5.2.2"
33+
related:
34+
url:
35+
- https://github.com/petergoldstein/dalli/security/advisories/GHSA-m252-9cgf-vx2w
36+
- https://github.com/petergoldstein/dalli/commit/61a9813
37+
- https://rubygems.org/gems/dalli/versions/5.2.2
38+
- https://github.com/petergoldstein/dalli/releases/tag/v5.2.2
39+
- https://rubygems.org/gems/dalli/versions/5.1.4
40+
- https://github.com/petergoldstein/dalli/releases/tag/v5.1.4
41+
- https://rubygems.org/gems/dalli/versions/5.0.10
42+
- https://github.com/petergoldstein/dalli/releases/tag/v5.0.10
43+
- https://rubygems.org/gems/dalli/versions/4.3.7
44+
- https://github.com/petergoldstein/dalli/releases/tag/v4.3.7
45+
notes: |
46+
- No CVE in GHSA.
47+
- "A CVE has been requested through GitHub but not yet
48+
assigned, so the entry has no cve: field."
49+
- No CVSS score in GHSA; GitHub severity is high.

‎gems/dalli/GHSA-p6pm-ch9v-44vx.yml‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
gem: dalli
3+
ghsa: p6pm-ch9v-44vx
4+
url: https://github.com/petergoldstein/dalli/security/advisories/GHSA-p6pm-ch9v-44vx
5+
title: Pipelined get_multi can return another key's value after an error reply
6+
date: 2026-10-05
7+
description: |
8+
Dalli's pipelined reply parser treated any reply line without a value
9+
body (for example `CLIENT_ERROR` or `SERVER_ERROR`) as the `MN` that
10+
ends the batch. It stopped reading that server's replies and left the
11+
rest on the connection, where later commands read them as their own
12+
replies, so a later `get` could return a different key's value.
13+
14+
memcached answers `CLIENT_ERROR` for a key over 250 bytes on the wire.
15+
Dalli checked key length in characters, before base64-encoding keys
16+
that need it, so a key of under 250 characters could still be too long.
17+
If any part of a cache key comes from user input, a user can trigger
18+
this and, in an application that caches per-user data, see another
19+
user's data. Affects multi-server `get_multi` (including Rails
20+
`read_multi`), `get_multi` with a block, and `get_multi_cas`, with the
21+
meta protocol (3.2.0 and later; the default since 5.0.0).
22+
23+
With the binary protocol (the default before 5.0), the same over-long
24+
key made memcached drop the connection, and `get` or `get_multi` with
25+
it retried forever, so a user-supplied key could hang requests.
26+
27+
### Workarounds
28+
29+
Keep user-controlled cache keys well under 250 bytes, for example by
30+
hashing them.
31+
patched_versions:
32+
- "~> 3.2.12"
33+
- "~> 4.3.6"
34+
- "~> 5.0.9"
35+
- "~> 5.1.3"
36+
- ">= 5.2.1"
37+
related:
38+
url:
39+
- https://github.com/petergoldstein/dalli/security/advisories/GHSA-p6pm-ch9v-44vx
40+
- https://github.com/petergoldstein/dalli/commit/e35c7ad
41+
- https://rubygems.org/gems/dalli/versions/5.2.1
42+
- https://github.com/petergoldstein/dalli/releases/tag/v5.2.1
43+
- https://rubygems.org/gems/dalli/versions/5.1.3
44+
- https://github.com/petergoldstein/dalli/releases/tag/v5.1.3
45+
- https://rubygems.org/gems/dalli/versions/5.0.9
46+
- https://github.com/petergoldstein/dalli/releases/tag/v5.0.9
47+
- https://rubygems.org/gems/dalli/versions/4.3.6
48+
- https://github.com/petergoldstein/dalli/releases/tag/v4.3.6
49+
- https://rubygems.org/gems/dalli/versions/3.2.12
50+
- https://github.com/petergoldstein/dalli/releases/tag/v3.2.12
51+
notes: |
52+
- No CVE in GHSA.
53+
- "A CVE has been requested through GitHub but not yet
54+
assigned, so the entry has no cve: field."
55+
- No CVSS score in GHSA; GitHub severity is high.

‎gems/dalli/GHSA-w39f-xq2m-4g8x.yml‎

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
---
2+
gem: dalli
3+
ghsa: w39f-xq2m-4g8x
4+
url: https://github.com/petergoldstein/dalli/security/advisories/GHSA-w39f-xq2m-4g8x
5+
title: Forking can resend buffered memcached requests and desynchronize the
6+
parent's connection
7+
date: 2026-10-05
8+
description: |
9+
Dalli buffered request bytes in Ruby's IO write buffer, and quiet
10+
(`multi`) blocks don't flush until they end. When the process forks,
11+
the child inherits the buffer, and Ruby flushes it when the child closes
12+
or finalizes the socket, even if the child never uses Dalli, so the
13+
request is sent twice: a buffered write is applied twice, or a buffered
14+
non-quiet request leaves the parent's connection off by one reply, so
15+
later reads return the previous key's value. Affects 4.2.0 and later.
16+
17+
With TLS, the child's close sends close_notify on the shared connection
18+
and tears down the parent's session. Affects all versions with TLS.
19+
20+
Applications that fork while threads use a shared client are affected
21+
(pre-forking servers, job runners).
22+
23+
The first fix was incomplete on 4.3.6 and 3.2.12: when another
24+
library's fork hook (such as connection_pool's, loaded before Dalli) ran
25+
first in the child, the parent's TLS session could still be ended, and
26+
4.3.6's write buffer kept a reference to the caller's value string with
27+
the meta protocol. Both are fixed in 4.3.7 and 3.2.13.
28+
29+
### Workarounds
30+
31+
Call `close` on Dalli clients before forking, outside any quiet block.
32+
patched_versions:
33+
- "~> 3.2.13"
34+
- "~> 4.3.7"
35+
- "~> 5.0.9"
36+
- "~> 5.1.3"
37+
- ">= 5.2.1"
38+
related:
39+
url:
40+
- https://github.com/petergoldstein/dalli/security/advisories/GHSA-w39f-xq2m-4g8x
41+
- https://github.com/petergoldstein/dalli/commit/62d5ad1
42+
- https://rubygems.org/gems/dalli/versions/4.3.7
43+
- https://github.com/petergoldstein/dalli/releases/tag/v4.3.7
44+
- https://rubygems.org/gems/dalli/versions/3.2.13
45+
- https://github.com/petergoldstein/dalli/releases/tag/v3.2.13
46+
- https://rubygems.org/gems/dalli/versions/5.2.1
47+
- https://github.com/petergoldstein/dalli/releases/tag/v5.2.1
48+
- https://rubygems.org/gems/dalli/versions/5.1.3
49+
- https://github.com/petergoldstein/dalli/releases/tag/v5.1.3
50+
- https://rubygems.org/gems/dalli/versions/5.0.9
51+
- https://github.com/petergoldstein/dalli/releases/tag/v5.0.9
52+
- https://rubygems.org/gems/dalli/versions/4.3.6
53+
- https://github.com/petergoldstein/dalli/releases/tag/v4.3.6
54+
- https://rubygems.org/gems/dalli/versions/3.2.12
55+
- https://github.com/petergoldstein/dalli/releases/tag/v3.2.12
56+
notes: |
57+
- No CVE in GHSA.
58+
- "A CVE has been requested through GitHub but not yet
59+
assigned, so the entry has no cve: field."
60+
- No CVSS score in GHSA; GitHub severity is medium.

‎gems/dalli/GHSA-wr87-m4jw-29x5.yml‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
gem: dalli
3+
ghsa: wr87-m4jw-29x5
4+
url: https://github.com/petergoldstein/dalli/security/advisories/GHSA-wr87-m4jw-29x5
5+
title: Per-request raw and the JSON serializer don't prevent unsafe
6+
deserialization
7+
date: 2026-10-05
8+
description: |
9+
1. Per-request `raw: true` was ignored by some read methods, which still
10+
ran the configured serializer's `load` (Marshal by default) on values
11+
whose flags say they're serialized: in 5.1 and 5.2, `get_multi`,
12+
`get_multi_cas`, `get_multi_with_metadata`, `get_cas` and
13+
`get_with_metadata`; in 5.0, `get_with_metadata`; in 4.x, `get`,
14+
`gat` and `fetch` with the binary protocol, and `get_with_metadata`;
15+
in 3.x, `get`, `gat` and `fetch`.
16+
2. `serializer: JSON` resolves to `JSON.load`. With the json gem before
17+
3.0, `JSON.load` honors `json_class` when the json additions are
18+
loaded, so a crafted value can instantiate classes that define
19+
`json_create`.
20+
21+
Exploiting either requires write access to the memcached instance and
22+
an application relying on per-request `raw: true` or `serializer: JSON`
23+
to avoid unsafe deserialization. Patched versions add
24+
`Dalli::JSONSerializer`, which reads with `JSON.parse`.
25+
26+
The first fix (5.2.1, 5.1.3, 5.0.9, 4.3.6 and 3.2.12) was incomplete:
27+
on 5.0, 4.3 and 3.2, `cas` and `cas!` (and `fetch_with_lock` on 5.0,
28+
and on 4.3 with the meta protocol) still deserialized values read with
29+
`raw: true`, and on every line but 3.2 a raw read still honored flags a
30+
reply carried unasked. Both are fixed in 5.2.2, 5.1.4, 5.0.10, 4.3.7
31+
and 3.2.13.
32+
33+
### Workarounds
34+
35+
Use a serializer that only parses data, such as one wrapping
36+
`JSON.parse`, instead of `serializer: JSON`.
37+
patched_versions:
38+
- "~> 3.2.13"
39+
- "~> 4.3.7"
40+
- "~> 5.0.10"
41+
- "~> 5.1.4"
42+
- ">= 5.2.2"
43+
related:
44+
url:
45+
- https://github.com/petergoldstein/dalli/security/advisories/GHSA-wr87-m4jw-29x5
46+
- https://github.com/petergoldstein/dalli/commit/8529428
47+
- https://rubygems.org/gems/dalli/versions/5.2.2
48+
- https://github.com/petergoldstein/dalli/releases/tag/v5.2.2
49+
- https://rubygems.org/gems/dalli/versions/5.1.4
50+
- https://github.com/petergoldstein/dalli/releases/tag/v5.1.4
51+
- https://rubygems.org/gems/dalli/versions/5.0.10
52+
- https://github.com/petergoldstein/dalli/releases/tag/v5.0.10
53+
- https://rubygems.org/gems/dalli/versions/4.3.7
54+
- https://github.com/petergoldstein/dalli/releases/tag/v4.3.7
55+
- https://rubygems.org/gems/dalli/versions/3.2.13
56+
- https://github.com/petergoldstein/dalli/releases/tag/v3.2.13
57+
- https://rubygems.org/gems/dalli/versions/5.2.1
58+
- https://github.com/petergoldstein/dalli/releases/tag/v5.2.1
59+
- https://rubygems.org/gems/dalli/versions/5.1.3
60+
- https://github.com/petergoldstein/dalli/releases/tag/v5.1.3
61+
- https://rubygems.org/gems/dalli/versions/5.0.9
62+
- https://github.com/petergoldstein/dalli/releases/tag/v5.0.9
63+
- https://rubygems.org/gems/dalli/versions/4.3.6
64+
- https://github.com/petergoldstein/dalli/releases/tag/v4.3.6
65+
- https://rubygems.org/gems/dalli/versions/3.2.12
66+
- https://github.com/petergoldstein/dalli/releases/tag/v3.2.12
67+
notes: |
68+
- No CVE in GHSA.
69+
- "A CVE has been requested through GitHub but not yet
70+
assigned, so the entry has no cve: field."
71+
- No CVSS score in GHSA; GitHub severity is low.

0 commit comments

Comments
 (0)