sistema: OPERATIVO
← volver a todos los hacks
SUPPLY CHAIN CRITICAL NEW

Bucket squatting en Vertex AI: la RCE cross-tenant «Pickle in the Middle»

Unit 42 reveló (16 de junio de 2026) un fallo en el SDK de Python de Vertex AI: un nombre de bucket de staging predecible y la falta de verificación de propiedad permitían secuestrar la subida de un modelo y lograr ejecución de código cross-tenant. Corregido en v1.148.0.

2026-06-22 // 6 min affects: google-vertex-ai, google-cloud-aiplatform <1.144.0

¿Qué es esto?

El 16 de junio de 2026, Unit 42 de Palo Alto Networks (investigador Ori Hadad) publicó Pickle in the Middle, la divulgación de una vulnerabilidad en el SDK de Python de Vertex AI (google-cloud-aiplatform) de Google Cloud. Antes del parche de Google, el fallo permitía a un atacante que operaba enteramente desde su propio proyecto de Google Cloud —con cero acceso al proyecto de la víctima— secuestrar la subida de un modelo de machine learning, envenenarlo y lograr ejecución remota de código dentro de la infraestructura de servicio de Vertex AI.

El error se reportó a través del Vulnerability Reward Program de Google el 5 de marzo de 2026 y se corrigió por completo antes de la divulgación pública: un primer parche en v1.144.0 (31 de marzo de 2026) y un segundo en v1.148.0 (15 de abril de 2026). Las versiones afectadas eran 1.139.0 y 1.140.0. Es un problema totalmente divulgado y parcheado: cubrimos el mecanismo y la lección, no un exploit accionable.

Cómo funciona

El ataque encadena dos debilidades de apariencia anodina.

Primero, un nombre de bucket por defecto predecible. Cuando un desarrollador sube un modelo sin especificar staging_bucket, el SDK construye un nombre de bucket de Cloud Storage según un patrón determinista basado en el ID de proyecto y la región. Como los nombres de bucket de GCS son únicos a nivel global en todo Google Cloud, cualquiera que pueda adivinar ese nombre puede precrearlo en su propio proyecto: una clase de ataque llamada bucket squatting (la misma lógica de colisión de nombres que el slopsquatting y la confusión de dependencias).

Segundo, una verificación de propiedad ausente. El SDK solo llamaba a bucket.exists() y, al encontrar el bucket (propiedad del atacante) ya presente, depositaba en silencio los artefactos de la víctima allí. El atacante concede los roles IAM adecuados para que tanto la subida de la víctima como el agente de servicio de Vertex AI tengan éxito: nada parece roto.

A partir de ahí es una carrera. El atacante prepara una Cloud Function en el evento google.storage.object.finalize: en cuanto llega el model.joblib de la víctima, se sustituye por un artefacto malicioso. Según la prueba de concepto de Unit 42, la ventana entre la subida de la víctima y la lectura del archivo por el Per-Product, Per-Project Service Account (P4SA) es de unos 2,5 segundos, mientras que la función disparada por el evento reacciona en unos 800 ms: suficiente para ganar la carrera siempre.

El payload aprovecha una propiedad bien conocida de la serialización en Python: los modelos de ML suelen almacenarse con pickle (o su envoltorio Joblib), y pickle.load() / joblib.load() ejecutan un método __reduce__ antes de cualquier validación. Cuando el agente de servicio de Vertex AI deserializaba el modelo reemplazado, el código del atacante se ejecutaba dentro del proyecto tenant gestionado por Google. En la prueba de Unit 42, ese código extrajo el token OAuth del contenedor de servicio desde el servidor de metadatos de GCE —un token que alcanzaba otros artefactos, metadatos de BigQuery, registros del tenant y nombres de clústeres GKE en el mismo tenant gestionado. Es el mismo sink de deserialización insegura que vemos en toda la pila de ML, desde la inyección de config de Transformers hasta la RCE del parser GGUF y el bypass trust-remote-code de vLLM.

Por qué importa

La víctima no hace nada mal. La reproducción usa llamadas estándar del SDK sin configuración inusualModel.upload() seguido de deploy(). La vulnerabilidad residía por completo en las herramientas de la plataforma y, aun así, el radio de impacto era ejecución de código cross-tenant y robo de credenciales sin ningún punto de apoyo, solo con conocer un ID de proyecto y una región (valores lejos de ser secretos).

También reubica la amenaza. La mayor parte de la atención en seguridad de LLM se centra en los prompts y los agentes; este caso recuerda que la cadena de suministro de modelos y las herramientas cloud del desarrollador son superficies de ataque de primer orden. Una convención de nombres más una verificación de propiedad omitida bastan para convertir un simple model.upload() en RCE dentro de la propia infraestructura del proveedor —un pariente de los problemas de privilegio del agente de servicio de Vertex AI documentados antes.

Defensas

  • Actualice el SDK. Lleve google-cloud-aiplatform a v1.148.0 o posterior. Los parches añaden un uuid4 aleatorio al nombre del bucket de staging (fin de la previsibilidad) y una verificación de propiedad del bucket antes de su uso.
  • Fije un bucket de staging explícito y propio. Defina siempre staging_bucket en una ubicación de Cloud Storage de su proyecto en lugar de confiar en el valor por defecto determinista. Unit 42 lo recomienda como práctica permanente incluso con el SDK parcheado.
  • Trate los artefactos de modelo como código no confiable. Todo lo deserializado vía pickle/Joblib puede ejecutarse al cargarse. Prefiera formatos seguros (por ejemplo safetensors) cuando sea posible, verifique la integridad de los artefactos (hashes/firmas) antes de desplegar y cargue modelos no confiables solo en contextos aislados de mínimo privilegio.
  • Acote el alcance de los agentes de servicio y los metadatos. Restrinja a qué pueden acceder las identidades de los contenedores de servicio; limite la exposición del servidor de metadatos y la salida (egress) para que un punto de apoyo por deserialización no pueda pivotar hacia tokens y recursos cross-tenant.
  • Vigile la clase de colisiones de nombres en general. El squatting de buckets/paquetes/namespaces siempre explota suposiciones de unicidad global. Audite cualquier herramienta que derive un nombre de recurso globalmente único a partir de entradas adivinables sin verificar la propiedad.

Estado

ElementoDetalle
Divulgación5 de marzo de 2026 (VRP de Google); público el 16 de junio de 2026
Afectadogoogle-cloud-aiplatform 1.139.0, 1.140.0
Primer parchev1.144.0 (uuid4 aleatorio en el nombre del bucket) — 31 de marzo de 2026
Parche completov1.148.0 (verificación de propiedad del bucket) — 15 de abril de 2026
ImpactoRCE cross-tenant, envenenamiento de modelo, robo de credenciales — cero acceso al proyecto víctima
Explotación observadaNo reportada

La lección no es «parchee Vertex AI y siga adelante». Es que las plataformas de IA heredan todas las debilidades clásicas del cloud —nombres de recursos predecibles, verificaciones de propiedad ausentes, deserialización insegura— y que la ruta de subida de modelos forma ahora parte de su superficie de ataque. Los defensores que ya fijaban buckets propios, verificaban artefactos y trataban los modelos serializados como código ejecutable nunca estuvieron expuestos.

Sources