CVE-2026-84372 — Vulnerability in predis/predis — CVE Details
CRITICAL
Predis: Redis command injection and denial of service via CRLF smuggling in pipelined commands on aggregate connections
Published September 8, 2026Updated September 8, 2026Source: osv
Summary
### Summary
An improper CRLF neutralization flaw in Predis' pipeline handling on
aggregate connections lets an unauthenticated attacker who can influence any
pipelined argument — a value **or** a key, e.g. a URL slug used as a cache key —
smuggle arbitrary Redis commands into the connection.
- On **cluster** connections (`cluster` option, incl. client-side sharding) this
is remote command injection: shard-wide `FLUSHDB`, targeted `DEL`/`SET`,
same-slot key theft via `GET`, cache poisoning, and possible node/cluster
outage.
- On **replication** connections (`replication` option) it is a reliable,
repeatable denial of service (uncaught fatal error) triggered by any value
containing `\r\n`.
### Details
When a pipeline is executed over an aggregate connection,
`AbstractAggregateConnection::write()` re-parses the already-serialized pipeline
buffer with `explode("\r\n")` instead of honoring RESP length prefixes:
- https://github.com/predis/predis/blob/v3.2.0/src/Connection/AbstractAggregateConnection.php#L78-L94
- splits the buffer on `\r\n`, ignoring `$<len>` bulk lengths,
- rebuilds each chunk via `Command::deserializeCommand()`
(https://github.com/predis/predis/blob/v3.2.0/src/Command/Command.php#L157)
to decide routing,
- writes each chunk to the connection chosen for that (fake) command.
RESP is length-prefixed, so the Redis **server** parses the original stream
correctly — but this second, client-side parser treats attacker-controlled
`\r\n` sequences as command boundaries. An argument such as:
PAD\r\n*1\r\n$7\r\nFLUSHDB
is a single data value to the server, but a complete, valid `FLUSHDB` command to
the re-parser. The consequence depends on the connection type:
- **Replication:** a pipeline forces `switchToMaster()`, so all chunks go to the
master and the byte stream stays intact — but the misaligned chunk makes
`deserializeCommand()` throw an uncaught `UnexpectedValueException: Invalid
serializing format`. Any value containing `\r\n` (binary serializers such as
igbinary/msgpack, or multi-line text) reliably crashes the request. This is
the crash tracked in #1574 — an unauthenticated, repeatable DoS.
- **Cluster:** chunks are routed to different nodes by slot, so the byte stream
is split across sockets. The smuggled command arrives on a node whose stream
is clean and is **executed**, though the application never sent it:
- `FLUSHDB` wipes an entire shard. It has no key but is routable because
`ClusterStrategy::getFakeKey()` hardcodes the fake key `'key'`
(https://github.com/predis/predis/blob/v3.2.0/src/Cluster/ClusterStrategy.php#L56
and #L243-L246), so the smuggled command always lands on the node serving
`slot('key')`.
- `INFO` (same fake-key routing) leaks server configuration via orphaned
responses; `CLUSTER FLUSHSLOTS` can take a node down.
- Same-slot `GET`/`SET`/`DEL` allow key theft (the reply is attributed to the
application's own later command on that slot), cache poisoning and targeted
data destruction; junk-key floods can exhaust node memory (OOM / mass
eviction of legitimate keys).
- Lua execution is **not** reachable: `EVAL` cannot be reconstructed (the
class is `EVAL_` due to the PHP reserved word), `EVAL_RO` fails the `Keys`
trait validation, and `EVALSHA` requires a pre-loaded script. This is
accidental, not a designed mitigation, and does not reduce severity —
`FLUSHDB`/`DEL`/`SET` alone already permit full cache wipes and data
destruction.
**Affected versions.** Introduced in v3.0.0 by PR #1438 ("Improved pipeline
abstractions"). Affected range: **3.0.0-RC1 through 3.2.0** (v3.0.0-alpha1 is not
affected — the vulnerable code was added after it). v1.x and v2.x are not
affected; their pipelines write per-command via `writeRequest()` and the
vulnerable code path does not exist.
Only `pipeline()` reaches the vulnerable sink; `transaction()` / `MULTI` paths do
not.
### Proof of concept
Two plain `redis:8` containers acting as two shards (PredisCluster shards
client-side, so Redis itself need not be in cluster mode); a PHP app on a
vulnerable Predis checkout (e.g. v3.2.0).
`docker-compose.yml`:
services:
redis1:
image: redis:8
ports: ["6391:6379"]
redis2:
image: redis:8
ports: ["6392:6379"]
`index.php` (a normal-looking app — slug from URL → cache lookup):
<?php
require __DIR__ . '/vendor/autoload.php';
$nodes = ['tcp://127.0.0.1:6391', 'tcp://127.0.0.1:6392'];
$client = new Predis\Client($nodes, ['cluster' => 'predis',
'parameters' => ['read_write_timeout' => 2]]);
if (isset($_GET['seed'])) {
for ($i = 1; $i <= 100; $i++) { $client->set("user:$i", "data$i"); }
exit('seeded');
}
$slug = $_GET['slug'] ?? '';
try {
[$doc] = $client->pipeline()->get("slug:$slug")->execute();
echo $doc ?: 'no such slug';
} catch (Throwable $e) {
http_response_code(500);
echo get_class($e);
}
Run:
composer require predis/predis:3.2.0
docker compose up -d
php -S 127.0.0.1:8080 -t .
curl 'http://127.0.0.1:8080/?seed' # 100 keys
Attack (smuggled `FLUSHDB` inside the slug):
curl 'http://127.0.0.1:8080/?slug=PAD4%0D%0A*1%0D%0A%247%0D%0AFLUSHDB'
The slug's first line must hash to a different shard than the fake key `'key'`
(otherwise the truncated bytes swallow the injection and the request simply
404s). With two shards this is ~50% per attempt — retry `PAD0`, `PAD1`, … until
the request returns 500. More shards make the attack **easier**: the per-attempt
hit probability is `(N-1)/N`, so on production clusters with many shards the
first request succeeds with near-certainty.
Verified result: `dbsize` across both shards drops 100 → 62; one shard was wiped
by a `FLUSHDB` the application never issued (it only ever ran `GET`/`SET` on
normal keys). The fix was confirmed A/B: the same PoC wipes a shard on the parent
of commit `053cb4b6` and fails on `053cb4b6`.
### Impact
CWE-93 (Improper Neutralization of CRLF Sequences) leading to Redis command
injection / protocol smuggling and denial of service. Any application on
**predis/predis 3.0.0-RC1 – 3.2.0** that calls `pipeline()` on a cluster or
replication connection and includes attacker-influenced data (values **or**
keys — e.g. cache keys built from URL slugs) in the pipelined commands is
affected. This is a common pattern for cache lookups, sessions and queued
writes.
- **Cluster:** unauthenticated remote command injection — shard-wide cache wipe
(`FLUSHDB`), targeted destruction (`DEL`), cache poisoning (`SET`), same-slot
key theft (`GET`), node memory exhaustion (key flood), possible cluster outage
(`CLUSTER FLUSHSLOTS`).
- **Replication:** reliable unauthenticated DoS on every affected request.
### Remediation
Upgrade to **predis/predis 3.3.0 or later**. The fix (PR #1586, commit
`053cb4b6`) makes pipelines on aggregate connections write each command using the
real `Command` object, eliminating the second, byte-splitting parser.
Users who cannot upgrade immediately should avoid calling `pipeline()` on
aggregate (cluster / replication) connections with any attacker-influenced keys
or values; there is no reliable in-application way to neutralize the embedded
`\r\n` while the second parser remains in the code path.
Advisory Timeline
First published September 8, 2026 (34 days ago).
Last revised September 8, 2026 — 0 days after initial publication.
Remediation
Upgrade to the fixed version using your package manager.
Composer
Update predis/predis to 3.3.0 or later
composer require "predis/predis:^3.3.0"
After upgrading, run your dependency scanner again to confirm the vulnerability is resolved.
Predis: Redis command injection and denial of service via CRLF smuggling in pipelined commands on aggregate connections This vulnerability has been assigned a severity rating of CRITICAL (CVSS score: 9.8/10).
How do I check if my project is affected by CVE-2026-84372?
CVE-2026-84372 affects predis/predis. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2026-84372 and 200,000+ other known vulnerabilities.
Severity & Exploitability
CVSS Score
9.8
Exploitation is straightforward and causes maximum impact. Patch immediately.