# Google Cloud Vertex AI Python SDK Bucket-Squatting ("Pickle in the Middle") Enables Cross-Tenant Model Hijacking and RCE

> Google Cloud's Vertex AI Python SDK (google-cloud-aiplatform 1.139.0/1.140.0) generated predictable Google Cloud Storage staging-bucket names from the project ID and region and validated only bucket existence, not ownership. Attackers could pre-create the expected bucket ("bucket squatting"), silently capture and swap a victim's model artifacts, and achieve cross-tenant remote code execution inside Vertex AI serving containers via pickle/joblib deserialization within a ~2.5-second race window. Resolved by UUID-randomized bucket names (1.144.0) and explicit ownership verification (1.148.0).

- **Published:** 2026-06-19T00:00:00Z
- **Last reviewed:** 2026-06-19T00:00:00Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-0880
- **ID:** TL-2026-0880
- **Severity:** HIGH
- **Category:** VULNERABILITY
- **Status:** PATCHED
- **Detections:** 9 · **IOCs:** 19 (full data via the Threadlinqs MCP server — Purple tier)

## Description

Unit 42 (Palo Alto Networks) researcher Ori Hadad disclosed a high-severity flaw in the Vertex AI Python SDK (google-cloud-aiplatform) dubbed "Pickle in the Middle." When a developer calls model/training APIs (e.g. aiplatform.init() and Model.upload()) without explicitly setting a staging bucket, the SDK's staging logic in gcs_utils.py — specifically the stage_local_data_in_gcs() flow — deterministically constructs a Google Cloud Storage bucket name as "<project>-vertex-staging-<location>" (e.g. my-project-vertex-staging-us-central1). The SDK then called staging_bucket.exists() and proceeded if the bucket merely existed, without verifying that the bucket belonged to the caller's project. Because GCS bucket names are a single global namespace, an attacker can predict and pre-create the victim's expected bucket in an attacker-controlled project ("bucket squatting") and open it with an allAuthenticatedUsers read/write IAM policy.

The full chain: (1) the attacker pre-creates the predicted bucket and grants allAuthenticatedUsers write access; (2) the attacker deploys a Cloud Function bound to a google.storage.object.finalize trigger on that bucket; (3) the victim runs an unconfigured Model.upload(), and the SDK silently stages the model artifact into the attacker's bucket; (4) the finalize-triggered Cloud Function swaps the legitimate artifact for a poisoned pickle within milliseconds; (5) the victim deploys the model with endpoint.deploy(); (6) the Vertex AI serving container calls joblib.load()/pickle.load() on the swapped artifact, executing the attacker's payload. Python's pickle format invokes a class's __reduce__ method during deserialization, so an attacker-controlled pickle runs arbitrary Python the instant it is loaded — before any validation.

The race is narrow but reliable: in Unit 42's proof of concept the victim's 601-byte model was uploaded at T+0ms, the Cloud Function detected the finalize event at T+804ms, replaced it with a 2,945-byte poisoned artifact at T+1,433ms, and Vertex AI's service agent read the poisoned model at T+2,460ms — a ~2.5-second window requiring near-real-time attacker automation. Post-exploitation, code running in the serving container queried the GCP instance metadata server and exfiltrated the token of the per-tenant service account custom-online-prediction@<tenant-project>.iam.gserviceaccount.com, which enabled same-tenant model theft from other deployments, BigQuery dataset/table enumeration and ACL access, and broader reconnaissance of tenant infrastructure (GKE clusters, container image URIs, logging). No exploitation in the wild was observed. Google rated the issue High under its Vulnerability Reward Program and shipped two fixes: UUID-randomized bucket naming in 1.144.0 (2026-03-31) and explicit bucket ownership verification in 1.148.0 (2026-04-15).

## MITRE ATT&CK

- T1583 Acquire Infrastructure
- T1587 Develop Capabilities
- T1608 Stage Capabilities
- T1195 Supply Chain Compromise
- T1199 Trusted Relationship
- T1059 Command and Scripting Interpreter
- T1204 User Execution
- T1648 Serverless Execution
- T1036 Masquerading
- T1552 Unsecured Credentials
- T1528 Steal Application Access Token
- T1580 Cloud Infrastructure Discovery
- T1526 Cloud Service Discovery
- T1069 Permission Groups Discovery
- T1530 Data from Cloud Storage
- T1080 Taint Shared Content
- T1537 Transfer Data to Cloud Account
- T1565 Data Manipulation

## Sources

- [Pickle in the Middle – Hijacking Vertex AI Model Uploads for Cross-Tenant RCE](https://unit42.paloaltonetworks.com/hijacking-vertex-ai-model/)
- [Google Cloud Vertex AI Allows Attacker to Hijack Victim's Model and Poison it](https://cybersecuritynews.com/google-cloud-vertex-ai-hijack-model/)
- [Google Vertex AI SDK Flaw Let Attackers Hijack Model Uploads via Bucket Squatting](https://thehackernews.com/2026/06/google-vertex-ai-sdk-flaw-let-attackers.html)
- [Google's Vertex AI SDK could allow RCE through bucket squatting](https://www.csoonline.com/article/4186193/googles-vertex-ai-sdk-could-allow-rce-through-bucket-squatting.html)
- [Google Cloud Vertex AI SDK flaw allowed model hijacking and code execution](https://www.scworld.com/brief/google-cloud-vertex-ai-sdk-flaw-allowed-model-hijacking-and-code-execution)
- [Google Cloud Vertex AI Vulnerability Lets Attackers Take Over and Poison AI Models](https://gbhackers.com/google-cloud-vertex-ai-vulnerability/)
- [Advisories for PyPI/google-cloud-aiplatform package](https://advisories.gitlab.com/pkg/pypi/google-cloud-aiplatform)

## Full data

Detection queries (Splunk SPL / Microsoft KQL / Sigma) and IOC values require the Threadlinqs MCP server (Purple tier): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-0880
