Uma verificação de segurança ausente em um endpoint de coleção GET permitiu que qualquer pessoa com uma conta básica do CoopCycle extraísse a lista completa de endereços de todas as lojas em uma instância compartilhada, expondo nomes, endereços residenciais e códigos postais de inúmeros clientes. A falha foi corrigida em dois dias, e os usuários são instados a atualizar para a versão mais recente lançada.
Como o vazamento aconteceu
O CoopCycle – uma plataforma de logística de código aberto usada por cooperativas de entrega de alimentos – define sua API com o framework PHP API Platform. Nesse framework, cada operação (POST, GET, etc.) deve ser acompanhada por uma expressão de segurança; se a expressão for omitida, o framework executa o código sem qualquer verificação de autorização.
Os desenvolvedores protegeram a requisição POST que cria ou atualiza a lista de endereços de uma loja com a expressão padrão is_granted('edit', object). Isso funciona porque a requisição visa uma única entidade de loja, fornecendo ao framework um "objeto" concreto para avaliar.
A requisição GET que lê o mesmo recurso visa uma coleção: /api/stores/{id}/addresses. Uma coleção não possui um único objeto, portanto, a mesma expressão is_granted('edit', object) não pode ser aplicada. Como os desenvolvedores deixaram a linha de segurança de fora, o framework serviu os dados de endereço para qualquer usuário autenticado, independentemente do tenant.
Em uma instância compartilhada do CoopCycle, um usuário malicioso poderia simplesmente iterar pelos IDs das lojas, emitir requisições GET para o endpoint e extrair os endereços residenciais de cada cliente armazenado no sistema. Nenhum privilégio extra foi necessário além de uma conta normal.
Por que o bug sobreviveu
O problema não foi um simples descuido. O modelo de segurança declarativo do API Platform carece de uma maneira direta de expressar que "o usuário deve pertencer ao mesmo tenant que cada objeto na coleção". A linha de código ausente estava exatamente onde o framework tornava a autorização trabalhosa.
Agravando o problema, a suíte de testes do projeto na verdade afirmava que a resposta GET contendo todos os endereços era o comportamento esperado. Em outras palavras, os testes automatizados passaram porque os fixtures usados nos testes permitiam o acesso entre tenants, mascarando efetivamente a vulnerabilidade. Uma suíte de testes "verde", neste caso, deu uma falsa sensação de segurança.
Quem ganha e quem perde
- Clientes: Suas informações de identificação pessoal (PII) – nomes completos e endereços residenciais – foram expostas a qualquer pessoa na plataforma. Embora os dados não tenham sido postados publicamente, a violação comprometeu a privacidade de múltiplas cooperativas.
- Cooperativas que utilizam o CoopCycle: A confiança na capacidade da plataforma de proteger os dados dos tenants foi abalada. Qualquer cooperativa que ainda não tivesse atualizado enfrentava o risco de exposição contínua.
- Os mantenedores do CoopCycle: Sua resposta rápida – uma correção em dois dias e a adição de testes de regressão – limitou a janela de exploração e demonstrou uma gestão responsável de código aberto. O incidente, no entanto, destaca a necessidade de processos de revisão de segurança mais rigorosos, especialmente em torno de padrões baseados em frameworks.
O que desenvolvedores e auditores devem procurar
- Assimetria de operação: Se um POST (ou qualquer operação de mutação) em um caminho é protegido, mas o GET correspondente está aberto, a discrepância é um sinal de alerta. O POST revela a intenção dos desenvolvedores de proteger o recurso.
- Endpoints de coleção: Qualquer coisa que retorne uma lista em vez de um único item geralmente fica fora dos padrões de segurança usuais. Verifique se as verificações de autorização são adicionadas explicitamente para leituras em massa.
- Realismo da suíte de testes: Garanta que os fixtures reflitam os limites reais de tenant. Um teste que passa e valida o vazamento de dados entre tenants é um sinal de alerta, não um sinal verde.
A correção e os próximos passos
Após a vulnerabilidade ser relatada, a equipe principal do CoopCycle adicionou a expressão de segurança ausente à operação de coleção GET e introduziu testes de regressão que impõem o isolamento de tenant tanto para endpoints de item único quanto de coleção. A correção foi lançada em uma versão subsequente do software.
Os usuários do CoopCycle devem:
- Verificar se estão executando uma versão recente do software.
- Revisar quaisquer extensões ou plugins personalizados que possam introduzir lacunas semelhantes no nível de coleção.
- Executar novamente as varreduras de segurança com foco em assimetrias de leitura/escrita em todas as rotas da API.
Conclusão
Frameworks que tornam a segurança declarativa podem ocultar lacunas perigosas quando os desenvolvedores dependem de padrões que funcionam apenas para objetos individuais. Uma verificação simples — o lado de leitura de um endpoint possui a mesma proteção que o lado de escrita? — pode revelar uma classe de vazamentos cross-tenant que, de outra forma, permaneceriam ocultos por trás de suítes de testes aprovadas.
