Incident · Mid
ChatGPT 3/20/2023: redis-py bug exposes other users' data
Real incident. Key points: pool corruption on a canceled request and data-owner check.
Short answer
Real incident. Key points: pool corruption on a canceled request and data-owner check. OpenAI took ChatGPT offline because of a bug in an open-source library: some users saw chat history titles from another active user. The problem came to light on March 20, 2023.
01 · CONTEXT
A user data cache shared by everyone
OpenAI took ChatGPT offline because of a bug in an open-source library: some users saw chat history titles from another active user. The problem came to light on March 20, 2023. It was also possible for the first message of a newly created conversation to appear in another person's history, if the two were active at around the same time.
The server uses Redis as a cache for user information, so it does not query the database on every request, and Redis Cluster to spread the load across several instances. The server is in Python, runs with Asyncio, and talks to Redis through the redis-py library.
The user sends the request to the application server.
The server queries the cache for the user's information.
The cache is a Redis Cluster, which spreads the load across several instances.
With the cache, the server avoids querying the database on every request.
02 · THE BUG
A reused connection carrying data from another request
The library keeps a connection pool shared between the server and the cluster and reuses each connection for another request when the previous one finishes. With Asyncio, request and response behave like two queues: the caller puts the request on the input queue, takes the response off the output queue, and only then returns the connection to the pool.
The server puts A's request on the input queue of a pool connection and will later read the response from the output queue.
A's request is canceled after entering the input queue and before the response leaves the output queue, and the connection is left corrupted.
An unrelated request, B's, reuses the pool connection and the next response may carry data left on it.
In most cases the leftover data is not of the expected type and the result is a server error, which the user resolves by trying again.
In some cases the data has the expected type, looks valid, and is delivered to B even though it belongs to another user.
The weak point is cancellation: if the request is canceled after entering the input queue and before the response leaves the output queue, the connection becomes corrupted and the next response, to an unrelated request, may receive data left on it. The Hacker News coverage describes the same mechanism: canceled requests could corrupt connections and return unexpected data from the cache.
| Situation | Resultado |
|---|---|
| Data left on the connection is not of the expected type (most cases) | Unrecoverable server error; the user has to try again |
| Data left on the connection is of the expected type (some cases) | What comes back from the cache looks valid, even though it belongs to another user |
03 · TRIGGER AND REACH
A server change and what became visible
At 1 a.m. Pacific time on Monday, March 20, OpenAI unintentionally introduced a server change that caused a spike in Redis request cancellations. This created a small probability of each connection returning wrong data. The bug only appeared in the redis-py Asyncio client for Redis Cluster, and has since been fixed.
The investigation showed that the same bug may have exposed payment information of 1.2% of active ChatGPT Plus subscribers during a nine-hour window. OpenAI states that full card numbers were not exposed at any time.
| Where | What could appear |
|---|---|
| Chat history | Titles of conversations from another active user |
| History after creating a conversation | The first message of a newly created conversation, if both were active at around the same time |
| Subscription confirmation email | Some emails in the window were sent to the wrong users |
| Manage subscription | Name, email, payment address, card type and last four digits, and expiration date of another active subscriber |
04 · THE RESPONSE
Fix the library and check the data owner
On identifying the bug, OpenAI reached out to the Redis maintainers with a patch. Among the actions to improve its systems, it added redundant checks to ensure the data returned by the cache matches the user who requested it; The Hacker News coverage records the same measure.
It also examined the logs programmatically to ensure messages were only available to the correct user, correlated several data sources to identify those affected and notify them, improved logging to confirm that the problem had stopped, and improved the robustness and scale of the Redis cluster to reduce connection errors under extreme load.
The server asks the cache for the user data.
Before using what came from the cache, a redundant check confirms that the data matches the user who requested it.
Better logging helps identify when the problem occurs and confirm that it has stopped.
The Redis cluster became more robust and scalable to reduce connection errors under extreme load.
05 · LESSONS
Questions for your design
The case suggests questions for your user data cache. Does every value read carry an owner identifier that the server verifies before using it? What happens to a shared connection when a request is canceled midway? Is there an monitoramento that warns when the returned data does not match who asked?
Frequently asked questions
What is ChatGPT 3/20/2023: redis-py bug exposes other users' data?
Real incident. Key points: pool corruption on a canceled request and data-owner check.
What does the ChatGPT 3/20/2023: redis-py bug exposes other users' data design cover?
It is organized in these sections: A user data cache shared by everyone, A reused connection carrying data from another request, A server change and what became visible, Fix the library and check the data owner, and Questions for your design.
How long is ChatGPT 3/20/2023: redis-py bug exposes other users' data and what level is it?
It takes about 12 minutes to read and is rated Mid level.
Now design it yourself
Run this case as an interview in the System Design school: you make the decisions, the tutor challenges them and you see how your design scores.