La falta de una comprobación de seguridad en un endpoint de colección GET permitió que cualquier persona con una cuenta básica de CoopCycle pudiera obtener la libreta de direcciones completa de todas las tiendas de una instancia compartida, exponiendo nombres, direcciones postales y códigos postales de innumerables clientes. El fallo fue corregido en dos días y se insta a los usuarios a actualizar a la última versión publicada.
Cómo ocurrió la filtración
CoopCycle, una plataforma de logística de código abierto utilizada por cooperativas de entrega de alimentos, define su API con el framework de PHP API Platform. En ese framework, cada operación (POST, GET, etc.) debe estar vinculada a una expresión de seguridad; si se omite la expresión, el framework ejecuta el código sin ninguna comprobación de autorización.
Los desarrolladores protegieron la petición POST que crea o actualiza la lista de direcciones de una tienda con la expresión estándar is_granted('edit', object). Esto funciona porque la petición se dirige a una única entidad de tienda, proporcionando al framework un "objeto" concreto para evaluar.
La petición GET que lee el mismo recurso apunta a una colección: /api/stores/{id}/addresses. Una colección no tiene un único objeto, por lo que no se puede aplicar la misma expresión is_granted('edit', object). Debido a que los desarrolladores omitieron la línea de seguridad, el framework sirvió los datos de las direcciones a cualquier usuario autenticado, independientemente del tenant al que perteneciera.
En una instancia compartida de CoopCycle, un usuario malintencionado podría simplemente iterar a través de los IDs de las tiendas, realizar peticiones GET al endpoint y extraer las direcciones particulares de cada cliente almacenado en el sistema. No se requirieron privilegios adicionales más allá de una cuenta normal.
Por qué el error sobrevivió
El problema no fue un simple descuido. El modelo de seguridad declarativo de API Platform carece de una forma directa de expresar que "el usuario debe pertenecer al mismo tenant que cada objeto de la colección". La línea de código faltante se encontraba exactamente donde el framework hacía que la autorización fuera engorrosa.
Para agravar el problema, la suite de pruebas del proyecto en realidad afirmaba que la respuesta GET que contenía todas las direcciones era el comportamiento esperado. En otras palabras, las pruebas automatizadas pasaban porque los fixtures utilizados en las pruebas permitían el acceso entre tenants, enmascarando eficazmente la vulnerabilidad. Una suite de pruebas en verde, en este caso, proporcionó una falsa sensación de seguridad.
Quién gana y quién pierde
- Clientes: Su información de identificación personal (PII) —nombres completos y direcciones particulares— quedó expuesta a cualquier usuario de la plataforma. Aunque los datos no se publicaron abiertamente, la brecha comprometió la privacidad de múltiples cooperativas.
- Cooperativas que utilizan CoopCycle: La confianza en la capacidad de la plataforma para salvaguardar los datos de los tenants se vio sacudida. Cualquier cooperativa que aún no se hubiera actualizado se enfrentaba al riesgo de una exposición continua.
- Los mantenedores de CoopCycle: Su rápida respuesta —un parche en dos días y la adición de pruebas de regresión— limitó la ventana de explotación y demostró una gestión responsable del código abierto. Sin embargo, el incidente resalta la necesidad de procesos de revisión de seguridad más estrictos, especialmente en torno a los valores predeterminados basados en frameworks.
Qué deben buscar los desarrolladores y auditores
- Asimetría de operaciones: Si una petición POST (o cualquier operación de mutación) en una ruta está protegida, pero el GET correspondiente está abierto, la discrepancia es una señal de alerta. El POST revela la intención de los desarrolladores de proteger el recurso.
- Endpoints de colección: Cualquier elemento que devuelva una lista en lugar de un solo ítem suele quedar fuera de los patrones de seguridad habituales. Verifique que se añadan explícitamente comprobaciones de autorización para las lecturas masivas.
- Realismo de la suite de pruebas: Asegúrese de que los fixtures reflejen los límites reales de los tenants. Una prueba que pasa y valida la fuga de datos entre tenants es una señal de advertencia, no una luz verde.
La solución y los siguientes pasos
Tras reportarse la vulnerabilidad, el equipo principal de CoopCycle añadió la expresión de seguridad faltante a la operación de colección GET e introdujo pruebas de regresión que imponen el aislamiento de tenants tanto para los endpoints de un solo elemento como para los de colecciones. El parche se incluyó en una versión posterior del software.
Los usuarios de CoopCycle deberían:
- Verificar que están ejecutando una versión reciente del software.
- Revisar cualquier extensión o plugin personalizado que pueda introducir brechas similares a nivel de colección.
- Volver a ejecutar los escaneos de seguridad centrándose en las asimetrías de lectura/escritura en todas las rutas de la API.
Conclusión
Los frameworks que hacen que la seguridad sea declarativa pueden ocultar brechas peligrosas cuando los desarrolladores confían en patrones que solo funcionan para objetos individuales. Una comprobación sencilla —¿tiene el lado de lectura de un endpoint la misma protección que el lado de escritura?— puede revelar una clase de filtraciones entre inquilinos que, de otro modo, permanecerían ocultas tras suites de pruebas exitosas.
