Threat reportCloud SecurityTL-2026-1648
GCP Cross-Project Compute Image Exfiltration via Compromised Developer Credentials
A demonstrated GCP attack chain shows how an attacker who phishes a developer's credentials and bypasses MFA can abuse overly broad cross-project IAM roles (compute.imageUser, compute.admin, storage.admin) to copy a confidential compute image into an attacker-pivot project, convert it to a Cloud Storage object via the Cloud Build API, and exfiltrate it with gsutil to an externally-controlled bucket in a separate GCP organization.
Key facts for GCP cross-project image exfiltration
| Identifiers | TL-2026-1648 |
|---|---|
| Also known as | GCP Compute Image Exfiltration Tutorial, Monstera-to-Cactus Exfiltration Chain |
| Severity | HIGH |
| Exploitation status | Public proof-of-concept exploit |
| Affected products | Google Google Cloud Platform - Compute Engine Images; Google Google Cloud Platform - Cloud Build; Google Google Cloud Storage |
| Weaknesses (CWE) | CWE-269, CWE-284, CWE-732 |
| Tools | gcloud CLI, gsutil |
| MITRE ATT&CK techniques | T1020 Automated Exfiltration, T1069.003 Cloud Groups, T1078.004 Cloud Accounts, T1111 Multi-Factor Authentication Interception, T1119 Automated Collection, T1526 Cloud Service Discovery, T1530 Data from Cloud Storage, T1537 Transfer Data to Cloud Account, T1548 Abuse Elevation Control Mechanism, T1550 Use Alternate Authentication Material, T1565 Data Manipulation, T1566 Phishing and 4 more in the attack flow |
| Motivation | UNKNOWN |
| Target sectors | technology, cloud-hosted-workloads, software-development |
| Target regions | Global |
| Detection rules | 9 (1 shown free) |
| Sources | 9 cited sources |
Detection coverage for GCP cross-project image exfiltration
As of 2026-07-23, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-1648 across Splunk SPL, Microsoft KQL and Sigma, covering 18 indicator(s) of compromise. The whole corpus is readable without an account. Every threat comes with one complete detection in Splunk SPL, Microsoft KQL and Sigma, free for everyone; a free account adds daily TL Creds to unlock the rest. Paid plans add a larger daily allowance, correlation and the MCP server. Threadlinqs MCP server · View plans.
Free detection: GCP Cross-Organization Storage Object Write to External Bucket
Detects the final exfiltration step: a storage.objects.create (or gsutil cp -r-driven write) targeting a bucket whose IAM policy grants access to a principal outside the source GCP organization, following storage.objects.list/get enumeration of the source object — the final stage of the Monstera-to-Cactus cross-organization image exfiltration chain.
- Languages: Splunk SPL, Microsoft KQL, Sigma
- ATT&CK: T1537, T1567.002, T1020
- Data sources: gcp_cloudaudit_data_access, gcp_iam_bucket_policy_reference
- Severity: critical
- Confidence: high
Splunk SPL
index=gcp sourcetype="google:gcp:pubsub:audit" data.protoPayload.methodName IN ("storage.objects.list","storage.objects.get","storage.buckets.get","storage.objects.create")
| eval bucket=mvindex(split(data.protoPayload.resourceName, "/"), 1)
| lookup gcp_bucket_org_lookup bucket OUTPUT bucket_org
| eval principal=data.protoPayload.authenticationInfo.principalEmail
| lookup gcp_principal_org_lookup principal OUTPUT principal_org
| where isnotnull(bucket_org) AND isnotnull(principal_org) AND bucket_org!=principal_org AND data.protoPayload.methodName="storage.objects.create"
| table _time, principal, principal_org, bucket, bucket_org, data.protoPayload.resourceNameMicrosoft KQL
GCPAuditLogs
| where TimeGenerated > ago(24h)
| where OperationName == "storage.objects.create"
| extend Bucket = tostring(split(tostring(parse_json(ProtoPayload).resourceName), "/")[1])
| extend Principal = tostring(parse_json(ProtoPayload).authenticationInfo.principalEmail)
| join kind=inner (GCPBucketOrgReference) on Bucket
| join kind=inner (GCPPrincipalOrgReference) on Principal
| where BucketOrg != PrincipalOrg
| project TimeGenerated, Principal, PrincipalOrg, Bucket, BucketOrg, ResourceName = tostring(parse_json(ProtoPayload).resourceName)Sigma
title: GCP Cross-Organization Storage Object Write to External Bucket
id: 8e2a1e2a-1648-4b2e-9f1a-tl20261648003
status: experimental
description: Detects a storage.objects.create write to a bucket whose IAM binding includes a principal from a different GCP organization than the source project, indicating the final cross-organization exfiltration step of the Monstera-to-Cactus chain.
references:
- https://www.mitiga.io/blog/google-cloud-platform-exfiltration-a-threat-hunting-guide
author: AII-Detector — ThreadLinqs Intelligence
date: 2026-07-23
tags:
- attack.exfiltration
- attack.t1537
- attack.t1567.002
- attack.t1020
- attack.collection
- attack.t1530
detection:
selection:
gcp.audit.method_name: 'storage.objects.create'
bucket_iam_binding: 'external_organization'
condition: selection
falsepositives:
- Approved partner data-sharing buckets with documented cross-org IAM grants (maintain an allowlist)
level: critical
logsource:
product: gcp
service: cloudauditKnown false positives:
- Approved partner data-sharing buckets with documented cross-org IAM grants — maintain an allowlist of sanctioned partner org IDs and bucket names
Tuning notes: Requires maintaining an org-ID reference lookup mapping bucket names and principal domains to their owning GCP organization; without it this detection cannot reliably distinguish cross-org writes from same-org writes, so populate/refresh the lookup via Cloud Asset Inventory exports.
- GCP Cross-Project Compute Image Copy — Sentinel Detection · unlock with TL Creds
- GCP Cloud Build Default Service Account Abuse for Image Export — Sentinel · unlock with TL Creds
- GCP Storage Metadata-Read Immediately Followed by External-Org Bucket Enumeration · unlock with TL Creds
- GCP Cross-Project Compute Image Copy — Sigma Rule · unlock with TL Creds
- GCP Cloud Build API Enabled Then Immediately Used for Image Export — Sigma Rule · unlock with TL Creds
- GCP IAM Grant of [indicator] to External-Organization Bucket for a [indicator] Principal · unlock with TL Creds
- GCP Cross-Project Compute Image Copy — sourceImage/resourceName Project Mismatch · unlock with TL Creds
- GCP Cloud Build API Enable Immediately Followed by Image Export · unlock with TL Creds
Indicators of compromise for GCP cross-project image exfiltration
As of 2026-07-23, Threadlinqs Intelligence tracks 18 indicators of compromise for TL-2026-1648.
How GCP cross-project image exfiltration works
Mitiga published a threat-hunting guide walking through a controlled-environment (proof-of-concept) exfiltration chain against Google Cloud Platform using a fictional victim developer ('Bob') and attacker ('Eve'). Eve first phishes Bob and bypasses his two-factor authentication to obtain valid GCP credentials scoped to the 'Aloe Vera' organization. Enumeration of Bob's IAM bindings reveals he holds compute.imageUser and project.viewer on a 'Monstera Project' containing a sensitive compute image, and compute.admin, storage.admin, roles/servicemanagement.serviceConsumer, and serviceusage.services.enable on a separate 'Cactus Project' that Bob can use as a pivot.
Because Bob lacks storage permissions in Monstera Project directly, Eve instead runs `gcloud compute images create` to copy the target compute image cross-project into Cactus Project, which logs as a `v1.compute.images.insert` event where the sourceImage path and the destination resourceName path point to two different projects -- the single highest-value detection signal in the whole chain. Eve then enables the Cloud Build API in Cactus Project (`google.api.serviceusage.v1.ServiceUsage.EnableService`) and issues `gcloud compute images export`, which causes the `cloudbuild` service account to call `compute.images.get` and `storage.objects.create` to convert the raw compute image into a GCS object inside a Cactus Project bucket -- resourceName strings for these objects typically contain 'log' or 'daisy' artifacts from the underlying Daisy image-export workflow.
For final exfiltration, Eve provisions an attacker-owned Google Cloud Storage bucket in a completely separate GCP organization, grants Bob's compromised account storage.object.admin (or equivalent legacy ACL) on that external bucket, and runs `gsutil cp -r` to recursively copy the exported image object out of Cactus Project into the external bucket. Mitiga notes a key visibility gap: GCP logs metadata-read operations on a storage object (storage.objects.get for metadata) identically to full object downloads, and destination-bucket write operations performed cross-organization do not appear in the source organization's audit logs -- meaning defenders monitoring only the source org will see reads/lists but never confirm the transfer completed, or vice versa depending on which side is monitored.
Although this is a documented tutorial rather than an observed in-the-wild intrusion, and there is no associated CVE, the underlying primitives it chains -- IAM over-permissioning across projects, Cloud Build default service-account abuse (cf. the related 'Bad.Build'/ConfusedFunction design flaw class publicly reported by Orca Security), and gsutil-based cross-organization bucket-to-bucket transfer -- are all live, exploitable misconfiguration classes in production GCP estates and map directly to MITRE ATT&CK Cloud techniques for valid cloud account abuse, cloud-to-cloud data transfer, and permission-groups discovery.
MITRE ATT&CK techniques by tactic:
Exfiltration
T1020 Automated Exfiltration; T1537 Transfer Data to Cloud Account; T1567.002 Exfiltration to Cloud Storage
Discovery
T1069.003 Cloud Groups; T1526 Cloud Service Discovery; T1580 Cloud Infrastructure Discovery
Initial Access
T1078.004 Cloud Accounts; T1566 Phishing
Privilege Escalation
T1078.004 Cloud Accounts; T1548 Abuse Elevation Control Mechanism
Defense Evasion
Credential Access
T1111 Multi-Factor Authentication Interception; T1621 Multi-Factor Authentication Request Generation
Collection
T1119 Automated Collection; T1530 Data from Cloud Storage
lateral-movement
T1550 Use Alternate Authentication Material
Impact
Resource Development
Remediation for GCP cross-project image exfiltration
Patches
- No vendor patch applicable; Google addressed the related Cloud Build default-service-account design flaw by changing the default to the Compute Engine service account and allowing custom scoped service accounts for builds
Immediate actions
- Audit and revoke unnecessary cross-project IAM bindings, especially compute.admin, storage.admin, and compute.imageUser granted to individual developer accounts spanning multiple projects
- Enable and review Cloud Audit Logs (Admin Activity + Data Access) for v1.compute.images.insert events where sourceImage and resourceName reference different project IDs
- Alert on serviceusage.services.enable calls that turn on the Cloud Build API in projects where it was previously disabled
- Restrict gsutil/storage.objects egress to known-good destination buckets via VPC Service Controls perimeters
- Enforce phishing-resistant MFA (FIDO2 security keys) for all developer accounts with cross-project IAM grants
Workarounds
- Disable automatic Cloud Build API enablement in projects that do not require it, and monitor EnableService calls
- Remove storage.objects.create/get and storage.buckets.get permissions from developer roles that only need compute image access
- Apply organization policy constraints (e.g. constraints/compute.storageResourceUseRestrictions, constraints/iam.allowedPolicyMemberDomains) to block cross-organization IAM bindings on storage buckets
Longer-term hardening
- Adopt least-privilege, project-scoped custom IAM roles instead of broad predefined roles (compute.admin, storage.admin) for developers
- Deploy Cloud Identity-Aware Proxy and context-aware access policies to restrict where privileged GCP sessions can originate
- Implement CIEM (Cloud Infrastructure Entitlement Management) tooling to continuously detect toxic combinations of cross-project permissions
- Migrate Cloud Build deployments off the legacy default (Compute Engine / Cloud Build) service account to scoped custom service accounts
- Deploy VPC Service Controls org-wide perimeters and egress access levels to block unauthorized cross-organization data movement
Affected and fixed versions
- Google — Google Cloud Platform - Compute Engine Images
Vulnerable versions: all versions using cross-project IAM with over-broad compute.imageUser/compute.admin grants
Fixed in: N/A - misconfiguration class, not a software version issue - Google — Google Cloud Platform - Cloud Build
Vulnerable versions: projects using default Cloud Build service account with project-editor-equivalent permissions (pre-2024 default behavior)
Fixed in: projects configured to use custom scoped service accounts or the reduced-privilege Compute Engine default service account for Cloud Build, per Google's 2024 default-behavior change - Google — Google Cloud Storage
Vulnerable versions: buckets without VPC Service Controls perimeters restricting cross-organization IAM bindings
Fixed in: N/A - mitigated via VPC Service Controls / org policy, not a patch
Timeline of GCP cross-project image exfiltration
- Rhino Security Labs documents 'Working-As-Intended' RCE-to-IAM privilege escalation via GCP Cloud Build, establishing Cloud Build as a known privilege-escalation vector referenced by the exfiltration chain.
- Praetorian publishes research cataloguing GCP service-account-based privilege escalation paths relevant to the locked-ioc-14/locked-ioc-15 pivot used in this chain.
- Mitiga publishes 'locked-ioc-7 Exfiltration: A Threat Hunting Guide' detailing the fictional Eve-vs-Bob cross-project compute image exfiltration walkthrough.
- Orca Security discloses 'Bad.Build' (ConfusedFunction), a critical design flaw in the default GCP Cloud Build service account enabling privilege escalation and supply-chain code tampering.
- CSO Online and Dark Reading report on the Bad.Build Cloud Build flaw and its implications for build-pipeline abuse in GCP environments.
- Google begins rolling out (through June 2024) a change to Cloud Build's default service account behavior: new projects running their first build now use the reduced-privilege Compute Engine default service account instead of the legacy Cloud Build service account with broad project-editor-equivalent permissions; existing projects that had already run builds remain on the legacy account unless migrated.
- wagov/wasocshared publishes a community security advisory summarizing the GCP Cloud Build privilege-escalation vulnerability class for SOC consumption.
- PwnedLabs publishes 'Exploiting GCP Cloud Build for Privilege Escalation', detailing how write access to a linked source repository lets an attacker modify cloudbuild.yaml to exfiltrate the build service account's OAuth token via the metadata endpoint and pivot to cloudbuild.builds.create-based trigger abuse -- a related Cloud Build service-account abuse primitive referenced by this exfiltration chain.
- TL-Intel-Harness ingests the Mitiga guide via RSS hunt phase and opens TL-2026-1648 as a detection-focused threat skeleton (no CVE, PoC tutorial, no confirmed in-the-wild campaign).
Sources cited for GCP cross-project image exfiltration
- Transfer Data to Cloud Account, Technique T1537 - Enterprise | MITRE ATT&CK MITRE · Research · 2026-07-23
- Valid Accounts: Cloud Accounts, Sub-technique T1078.004 - Enterprise | MITRE ATT&CK MITRE · Research · 2026-07-23
- Bad.Build: A Critical Privilege Escalation Design Flaw in Google Cloud Build Enables a Supply Chain Attack orca.security · Vendor report · 2024-04-15
- Google Cloud Platform (GCP) Service Account-based Privilege Escalation paths praetorian.com · Research · 2021-01-01
- Working-As-Intended: RCE to IAM Privilege Escalation in GCP Cloud Build rhinosecuritylabs.com · Research · 2020-01-01
- Google Cloud Platform Exfiltration: A Threat Hunting Guide mitiga.io · Blog · 2023-02-22
- Exploiting GCP Cloud Build for Privilege Escalation blog.pwnedlabs.io · Blog · 2024-01-01
- Google Cloud Build Flaw Enables Privilege Escalation, Code Tampering Dark Reading · News · 2024-04-15
- Attackers can abuse Google Cloud Build to poison production environments csoonline.com · News · 2024-04-16
Drafted by the Threadlinqs research pipeline from 9 sources; published ; last updated —.