Published
- 5 min read
By Allan D - Editor, AI Security Wire
Pickle in the Middle: Vertex AI SDK Flaw Enabled Cross-Tenant RCE
On June 16, Palo Alto Networks Unit 42 published the details of a flaw they call “Pickle in the Middle”: a bucket squatting vulnerability in the Vertex AI Python SDK that, under the right conditions, allowed an attacker with no credentials and no access to a victim’s Google Cloud project to hijack model uploads and execute code inside Google’s own AI serving infrastructure. The researchers reported the issue on March 5, 2026. Google issued a complete fix six weeks later. Disclosure came yesterday.
The name is apt. The attack sits between a victim’s model upload and the serving environment that loads it, and it exploits one of the oldest footguns in Python ML: the pickle format.
How the Staging Bucket Got Squatted
The vulnerability lived in how the Vertex AI SDK chose a temporary Cloud Storage bucket when a user called the model upload workflow without specifying one. Instead of generating a random name, the SDK derived the bucket name from the user’s GCP project ID and region, producing something like project-vertex-staging-us-central1.
That naming scheme is predictable. A project ID is often public, appearing in API requests, documentation, and developer tooling. An attacker who knows the project ID can calculate the expected bucket name in advance and register it in their own GCP account, a move called bucket squatting. Cloud storage bucket names are globally unique across all accounts, so the first to claim a name owns it.
When the victim’s SDK went to upload model artifacts, it checked whether the expected bucket existed. It did. What it did not check was whether the victim owned that bucket. The upload proceeded, and the model files landed in attacker-controlled storage.
Unit 42 confirmed the flaw in SDK versions 1.139.0 and 1.140.0, both of which were the latest available at the time of their investigation. No CVE has been assigned.
Pickle Deserialization: The Execution Step
Controlling the upload destination is one thing. Getting code to execute is another. That is where pickle comes in.
Python’s native pickle serialisation format is the default for many ML frameworks, including scikit-learn and joblib. A pickle file is not passive data: when deserialised, it can execute arbitrary Python code. This property has been documented as a risk for over a decade, but it persists in production ML pipelines because it is the path of least resistance for saving and loading models.
Unit 42’s attack scenario replaces the victim’s legitimate model artifacts in the attacker-controlled bucket with a crafted pickle payload. When Vertex AI’s serving infrastructure subsequently pulls the model from that bucket and loads it, the pickle deserialises and the payload runs inside Google’s serving environment. The code executes with the privileges of the serving process, across the boundary from the attacker’s tenant into Google’s infrastructure and potentially into the victim’s serving context.
The researchers describe this as cross-tenant RCE: the attacker, operating from their own GCP account with no relationship to the victim, achieves code execution in serving infrastructure shared with the victim.
The Fix
Google’s response had two parts.
The first patch, shipped in v1.144.0 on March 31, added a random UUID to the generated bucket name. This makes the name unpredictable, breaking the squatting precondition.
The second patch, in v1.148.0 on April 15, added bucket ownership verification to the Model.upload() workflow. Before proceeding with an upload, the SDK now confirms that the staging bucket is owned by the calling project. If the bucket exists but belongs to another account, the upload fails rather than proceeding silently.
The ownership verification is the more robust fix. The UUID approach raises the bar for guessing but does not eliminate the structural problem: a bucket name without ownership enforcement is still squattable in principle, just harder to predict.
What ML Practitioners Should Check
Update the SDK. Anyone using the Vertex AI SDK for Python should confirm they are on version 1.148.0 or later. The specific risk is in the model upload workflow when no staging bucket is explicitly provided.
Specify your own bucket explicitly. Even on a patched SDK, explicitly setting a staging bucket you own removes any dependency on generated names. This is good practice regardless of this vulnerability.
Audit model load paths. The underlying pickle deserialization risk is not unique to Vertex AI. Any pipeline that loads ML models from cloud storage using pickle or joblib, where the storage path is not cryptographically verified, is vulnerable to a similar poisoning attack if an attacker can modify the artifact at rest. Consider model signing, or switching to serialisation formats that do not allow arbitrary code execution on load.
GCP storage ACLs. Review whether your GCP project’s staging and artifact buckets have overly permissive ACLs. Bucket squatting requires that the SDK checks bucket existence without ownership verification, but defence in depth means your legitimate buckets should not be publicly readable or writable by other accounts.
The vulnerability was patched quietly in April and disclosed publicly yesterday. No exploitation in the wild has been reported. The technical bar for exploitation was low enough, and the impact severe enough, that any Vertex AI user running a version below 1.148.0 should treat updating as a priority action rather than a routine upgrade.
References
- The Hacker News — Google Vertex AI SDK Flaw Let Attackers Hijack Model Uploads via Bucket Squatting
- Palo Alto Networks Unit 42 — Pickle in the Middle: Hijacking Vertex AI Model Uploads for Cross-Tenant RCE
- CSO Online — Google’s Vertex AI SDK could allow RCE through bucket squatting
- GBHackers — Google Cloud Vertex AI Vulnerability Lets Attackers Take Over and Poison AI Models
Frequently Asked Questions
- What was the Vertex AI SDK bucket squatting vulnerability?
- If a user did not specify a staging bucket when uploading a model, the Vertex AI Python SDK generated a bucket name derived only from the project ID and region, in the format project-vertex-staging-region. The SDK checked whether that bucket existed but not whether the caller owned it. An attacker who knew the victim's project ID could pre-create the same bucket in their own GCP project. The SDK would silently upload the victim's model artifacts to the attacker-controlled bucket instead.
- How did bucket squatting lead to code execution?
- Once an attacker controlled the staging bucket, they could swap the uploaded model artifacts for a poisoned replacement. Python ML models are commonly serialised with pickle or joblib, both of which execute arbitrary code when deserialized. When the victim's Vertex AI serving infrastructure loaded the model back from the attacker-controlled bucket, the malicious pickle payload ran inside Google's own serving environment, crossing the tenant boundary.
- Is this vulnerability still a risk, and was it exploited?
- Google patched the flaw in Vertex AI SDK for Python versions 1.144.0 and 1.148.0, released March 31 and April 15, 2026 respectively. No in-the-wild exploitation was observed before or during the disclosure period. Any user on a version prior to 1.148.0 who did not specify an explicit staging bucket remains vulnerable unless they have updated.