Incidente · Pleno
ChatGPT 20/03/2023: bug no redis-py expõe dados de outros usuários
Incidente real. Pontos centrais: corrupção de pool em requisição cancelada e checagem de dono do dado.
Resposta curta
Incidente real. Pontos centrais: corrupção de pool em requisição cancelada e checagem de dono do dado. A OpenAI tirou o ChatGPT do ar por causa de um bug numa biblioteca de código aberto: alguns usuários viam títulos do histórico de outro usuário ativo. O problema veio à tona em 20 de março de 2023.
01 · CONTEXTO
Um cache de dados de usuário compartilhado por todos
A OpenAI tirou o ChatGPT do ar por causa de um bug numa biblioteca de código aberto: alguns usuários viam títulos do histórico de outro usuário ativo. O problema veio à tona em 20 de março de 2023. Também era possível que a primeira mensagem de uma conversa recém-criada aparecesse no histórico de outra pessoa, se as duas estivessem ativas na mesma época.
O servidor usa o Redis como cache de informações de usuário, para não consultar o banco a cada requisição, e o Redis Cluster para distribuir a carga por várias instâncias. O servidor é em Python, roda com Asyncio e fala com o Redis pela biblioteca redis-py.
O usuário envia a requisição ao servidor da aplicação.
O servidor consulta o cache com as informações do usuário.
O cache é um Redis Cluster, que distribui a carga por várias instâncias.
Com o cache, o servidor evita consultar o banco a cada requisição.
02 · O BUG
Uma conexão reaproveitada com dados de outra requisição
A biblioteca mantém um pool de conexões compartilhado entre o servidor e o cluster e reaproveita cada conexão em outra requisição quando a anterior termina. Com Asyncio, requisição e resposta se comportam como duas filas: quem chama coloca a requisição na fila de entrada, retira a resposta da fila de saída e só então devolve a conexão ao pool.
O servidor coloca a requisição de A na fila de entrada de uma conexão do pool e depois lerá a resposta na fila de saída.
A requisição de A é cancelada depois de entrar na fila de entrada e antes de a resposta sair da fila de saída, e a conexão fica corrompida.
Uma requisição sem relação, a de B, reaproveita a conexão do pool e a próxima resposta pode trazer dados deixados nela.
Na maioria dos casos o dado deixado não é do tipo esperado e o resultado é um erro de servidor, que o usuário resolve tentando de novo.
Em alguns casos o dado tem o tipo esperado, parece válido e é entregue a B mesmo pertencendo a outro usuário.
O ponto frágil é o cancelamento: se a requisição é cancelada depois de entrar na fila de entrada e antes de a resposta sair da fila de saída, a conexão se corrompe e a próxima resposta, de uma requisição sem relação, pode receber dados deixados nela. A cobertura do The Hacker News descreve o mesmo mecanismo: requisições canceladas podiam corromper conexões e devolver dados inesperados do cache.
| Situação | Resultado |
|---|---|
| Dado deixado na conexão não tem o tipo esperado (maioria dos casos) | Erro de servidor sem recuperação; o usuário precisa tentar de novo |
| Dado deixado na conexão tem o tipo esperado (alguns casos) | O que volta do cache parece válido, mesmo pertencendo a outro usuário |
03 · GATILHO E ALCANCE
Uma mudança no servidor e o que ficou visível
Às 1h, horário do Pacífico, da segunda-feira 20 de março, a OpenAI introduziu sem querer uma mudança no servidor que causou um pico de cancelamentos de requisições ao Redis. Isso criou uma pequena probabilidade de cada conexão devolver dado errado. O bug só aparecia no cliente Asyncio do redis-py para Redis Cluster, e já foi corrigido.
A investigação mostrou que o mesmo bug pode ter exposto informações de pagamento de 1,2% dos assinantes do ChatGPT Plus ativos numa janela de nove horas. A OpenAI afirma que números completos de cartão não foram expostos em nenhum momento.
| Onde | O que podia aparecer |
|---|---|
| Histórico de conversas | Títulos de conversas de outro usuário ativo |
| Histórico após criar uma conversa | A primeira mensagem de uma conversa recém-criada, se ambos estivessem ativos na mesma época |
| E-mail de confirmação de assinatura | Alguns e-mails da janela foram enviados aos usuários errados |
| Gerenciar assinatura | Nome, e-mail, endereço de pagamento, tipo e final do cartão e validade de outro assinante ativo |
04 · A RESPOSTA
Corrigir a biblioteca e checar o dono do dado
Ao identificar o bug, a OpenAI procurou os mantenedores do Redis com um patch. Entre as ações para melhorar os sistemas, adicionou checagens redundantes para garantir que o dado devolvido pelo cache corresponda ao usuário que pediu; a cobertura do The Hacker News registra a mesma medida.
Também examinou os logs por programa para garantir que as mensagens só ficassem disponíveis ao usuário correto, correlacionou várias fontes de dados para identificar os afetados e notificá-los, melhorou o logging para confirmar que o problema parou e melhorou a robustez e a escala do cluster Redis para reduzir erros de conexão sob carga extrema.
O servidor pede o dado de usuário ao cache.
Antes de usar o que veio do cache, uma checagem redundante confere se o dado corresponde ao usuário que pediu.
Logging melhor ajuda a identificar quando o problema ocorre e a confirmar que ele parou.
O cluster Redis ficou mais robusto e escalável para reduzir erros de conexão sob carga extrema.
05 · LIÇÕES
Perguntas para o seu desenho
O caso sugere perguntas para o seu cache de dados de usuário. Cada valor lido carrega uma identificação de dono que o servidor confere antes de usar? O que acontece com uma conexão compartilhada quando uma requisição é cancelada no meio? Existe monitoramento que avise quando o dado devolvido não bate com quem pediu?
Perguntas frequentes
O que é ChatGPT 20/03/2023: bug no redis-py expõe dados de outros usuários?
Incidente real. Pontos centrais: corrupção de pool em requisição cancelada e checagem de dono do dado.
O que o design de ChatGPT 20/03/2023: bug no redis-py expõe dados de outros usuários cobre?
Ele está organizado nestas seções: Um cache de dados de usuário compartilhado por todos, Uma conexão reaproveitada com dados de outra requisição, Uma mudança no servidor e o que ficou visível, Corrigir a biblioteca e checar o dono do dado e Perguntas para o seu desenho.
Quanto tempo leva ChatGPT 20/03/2023: bug no redis-py expõe dados de outros usuários e qual é o nível?
Leva cerca de 12 minutos para ler e tem nível Pleno.
Agora projete você mesmo
Rode este caso como uma entrevista na escola de System Design: você toma as decisões, o tutor as questiona e você vê a nota do seu desenho.