In early 2023, a troubling vulnerability called CVE-2023-28859 shook users of the popular Python Redis client, redis-py. If you’re running redis-py before 4.4.4 or any 4.5.x version before 4.5.4, keep reading. There’s a good chance your setup is affected.

Let’s break down what went wrong, why it’s dangerous, how it might be exploited, and (most importantly) how you can patch this issue.

What Is CVE-2023-28859?

In short, redis-py, when used with *async* commands, may leak response data from one client’s request into another client’s response. This typically happens if a connection is left open after an async command is canceled at just the wrong time (for example, when not using Redis pipelines).

In practical terms: *One client can accidentally see data meant for another.* For multi-user systems, this is a privacy and security disaster.

The *async* API, using AsyncIO

- Non-pipeline operations (though pipeline is less affected, the risk is general to AsyncIO connections)

How Does the Vulnerability Work?

AsyncIO connections make code non-blocking and highly performant – but managing in-progress connections is tricky. Here’s a scenario that triggers the leak:

Before the response arrives, Client A cancels their request (maybe due to a timeout).

3. The redis-py connection is returned to the connection pool without being closed/cleaned up properly.

Client B gets the same connection and sends a totally different request.

5. When Client B gets their reply, it may actually be Client A’s response (e.g., "secret1" value).

That’s “cross-talk” between unrelated requests—one of the worst things that can happen in a multi-tenant system.

Code Example: Triggering the Bug

Here’s an (oversimplified) example that shows the *broken* behavior.

> Do NOT use this in production. This is for education!

import asyncio
import redis.asyncio as redis

async def leaky_getting(r, key):
    try:
        result = await asyncio.wait_for(r.get(key), timeout=.1)  # Timeout triggers cancel
    except asyncio.TimeoutError:
        print(f"Request for {key} canceled (timeout reached) – connection likely leaked!")
        return None
    return result

async def innocent_getting(r, key):
    result = await r.get(key)
    print(f"Innocent get for {key}: {result}")
    return result

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

    # Simulate a canceled request
    task1 = asyncio.create_task(leaky_getting(r, "secret1"))
    await asyncio.sleep(.05)  # Give the above task some time to start

    # Innocent connection tries to use the pool (may get a polluted connection)
    task2 = asyncio.create_task(innocent_getting(r, "profile_info"))

    await asyncio.gather(task1, task2)

asyncio.run(main())

Depending on timing, innocent_getting could receive the result meant for leaky_gettingthat’s CVE-2023-28859 in action.

Confidential Data Leak: Sensitive responses might be given to the wrong user!

- Hard to Detect/Debug: The race condition is subtle and doesn’t always trigger.

Listens for accidental data leaks in the responses

While not trivial to weaponize (needs control over timing and AsyncIO), it’s enough of a risk that fixing is urgently recommended.

How Did the redis-py Team Fix It?

You can find the redis-py fix here:  
🔗 redis-py pull request #2496

Mitigation:  
- When an async connection is canceled or raises an exception, it is *always closed* before being returned to the pool.

AsyncIO connection handling was hardened to avoid any response “bleed” across unrelated clients.

The CHANGELOG for version 4.4.4 and 4.5.4 notes the security fix.

How To Patch CVE-2023-28859

1. Upgrade immediately:  

pip install --upgrade 'redis>=4.4.4'


or

pip install --upgrade 'redis>=4.5.4'

2. Double-check your dependency tree:
Some frameworks (e.g., Celery, Django with Channels) may pin older redis-py versions; check your requirements.txt.

3. Test with concurrency:
If you rely on async Redis and identify odd cross-user data issues, re-test post-upgrade.

Official References

- NVD Official Entry for CVE-2023-28859
- redis-py security advisory (GitHub)
- Pull Request with the Fix
- Changelog 4.4.4
- Changelog 4.5.4

Always keep dependencies up-to-date!

- Handle async cancellations cleanly in your applications, or you might be opening doors not just to bugs, but serious security problems.
- For critical deployments, test for cross-user privacy leaks. Vulnerabilities like CVE-2023-28859 are subtle but dangerous.

If you’re a dev, ops, or infosec professional working with async Redis in Python: patch now, audit your code, and spread the word. This one’s nasty.


*Post written exclusively for (your team/blog/website). Share knowledge, not vulnerabilities.*

Timeline

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