Skip to content

This tool is not affiliated with, endorsed by or sponsored by Google LLC. Google Cloud and Google Cloud Platform are trademarks of Google LLC. Other names are trademarks of their respective owners.

Google Cloud incident response: a compromised project

Your Google Cloud project may be compromised. The order of operations: contain the identity, preserve the audit logs, scope with methodNames, then eradicate.

Published on 7 min read

TL;DR. Treat a suspected Google Cloud compromise as an identity incident first. Disable the credential in use (usually a user-managed service account key or a user session), copy the Cloud Audit Logs out of the project before anyone with Owner rights can touch them, then scope with a short list of methodNames: CreateServiceAccountKey, SetIamPolicy, setMetadata, storage.objects.get, DeleteSink. Only then clean up. The free in-browser analyzer runs those detections on an export and gives you a verdict, a timeline and a checklist.

Most Google Cloud incidents I see do not start with an exotic exploit. Google's own Cloud Threat Horizons report (H2 2025) attributes 47.1% of the initial access it observed in H1 2025 to weak or absent credentials and 29.4% to misconfiguration. In practice that means a key file in a repository, a CI variable printed in a build log, or a VM with a weak password. The attacker then does what the permissions allow: grant themselves Owner, start miners, read buckets, and switch off what could alert you.

This guide is the order of operations. Each step links to a deeper article in the series.

Phase 1: triage in the first hour

You have a signal: a billing spike, a Security Command Center finding, an email from Google about an exposed key, or a strange IAM member. Answer three questions fast.

  1. Which identity? A service account email (…@PROJECT.iam.gserviceaccount.com), a user, or a personal Gmail account that should not be there.
  2. Which credential? If audit entries carry authenticationInfo.serviceAccountKeyName, the caller used a user-managed key. If they carry serviceAccountDelegationInfo, someone impersonated a service account and the real actor is further up the chain.
  3. Is it still active? Look at the last entry for that principal and caller IP.

A first Logs Explorer query is enough to answer these:

logName:"cloudaudit.googleapis.com"
protoPayload.authenticationInfo.principalEmail="ci-deployer@PROJECT.iam.gserviceaccount.com"

Phase 2: contain the identity, not the symptoms

Deleting the miner VM feels productive, but if the key that created it still works, it will be back in minutes. Google's guidance for compromised credentials lists the actions per credential type. The ones that matter most:

Credential in useContainment
User-managed service account keyDisable the key (then delete once you have its ID in your notes); rotate what the service account could read
ImpersonationRemove the Token Creator / Service Account User binding from the caller; disable the caller
User or Gmail account in IAMRemove the binding; if it is one of your users, sign it out and reset the password
OAuth tokens (gcloud)Revoke the token; enforce session control for Cloud access

Then check the IAM policy for other additions. Attackers who obtain Owner rarely stop at one binding. The IAM policy abuse article shows how to read bindingDeltas to list every change.

Phase 3: preserve the evidence before it expires or disappears

Two things destroy cloud evidence: retention and the attacker.

  • Retention. The _Required bucket keeps Admin Activity and System Event audit logs for 400 days and cannot be modified; the _Default bucket keeps everything else, including Data Access logs, for 30 days by default (quotas and limits, routing overview).
  • The attacker. With Owner rights they can delete log sinks, add exclusions, shorten _Default retention or delete logs. See defense evasion in Google Cloud.

Export now, widely: the whole suspected period plus a few weeks of baseline, every audit log type, and VPC Flow Logs if they exist. The console download caps at 10,000 entries per download (Logs Explorer interface), so for anything bigger use gcloud logging read or copy the sink bucket. Cloud Audit Logs explained covers each export path.

Phase 4: scope with a short list of methodNames

You do not need to read every entry. A handful of protoPayload.methodName values answer most scoping questions:

QuestionWhere to lookDeep dive
Was a key created or uploaded?google.iam.admin.v1.CreateServiceAccountKey, UploadServiceAccountKeyLeaked service account key
Who impersonated whom?iamcredentials.googleapis.com GenerateAccessToken, SignBlob, SignJwt; serviceAccountDelegationInfoService account impersonation
Did anyone gain Owner?SetIamPolicy with bindingDeltas ADD roles/ownerSetIamPolicy abuse
Are VMs backdoored or mining?compute.instances.setMetadata, setCommonInstanceMetadata, compute.instances.insert with acceleratorsCompute Engine abuse
Was data taken?storage.objects.get bursts, storage.setIamPermissions with allUsers, BigQuery copy jobsGCS and BigQuery exfiltration
Did data leave through the network?VPC Flow Logs, bytes per external IPVPC Flow Logs analysis
Did they blind you?DeleteSink, UpdateSink, CreateExclusion, auditConfigDeltas REMOVEDefense evasion

Pivot on two keys throughout: the caller IP (protoPayload.requestMetadata.callerIp) and the principal. An attacker IP that appears for a service account key and then for a brand-new Gmail Owner links the two stages together. The analyzer does exactly this correlation and raises an "attack chain" finding when the same IP or principal moves from access to takeover actions.

Note that callerIp is not always a public address: Google documents that calls between Google services show private, and calls from VMs without external IPs may show the internal address or gce-internal-ip (AuditLog reference).

Phase 5: eradicate and recover

Once the scope is known, remove every foothold in one pass, otherwise the attacker notices and moves:

  • delete the keys, HMAC keys and service accounts created by the attacker;
  • remove the IAM bindings, restore relaxed organization policies;
  • rebuild (do not clean) VMs whose startup scripts or SSH keys were changed, after snapshotting their disks;
  • make buckets private again and enforce public access prevention;
  • restore sinks and Data Access logging, ideally to an aggregated sink in a project the workload owners cannot administer.

The tool's remediation checklist is generated from the findings in that order: containment first, then persistence, then logging.

Phase 6: close the gaps that made it possible

The post-incident list is usually the same:

Where the analyzer fits

The GCP Forensics analyzer takes the exports from phase 3 and runs the scoping of phase 4: 32 rules, 5 stateful analytics and one attack-chain correlation, all published in the page's rules table. It runs in your browser; the logs are not uploaded. The step-by-step guide shows the workflow, and the fictional walkthrough shows the output on a complete incident.

It does not replace judgment. A key used from a CI provider's IP or an Owner granted to a consultant can be legitimate; confirm each finding with its owner. And GKE audit entries are set aside for Kubernetes Forensics, Workspace entries for Google Workspace Forensics.

Frequently asked questions

What is the first thing to do when a Google Cloud project is compromised?

Stop the credential the attacker is using (disable the service account key, suspend the user, revoke tokens) and, in the same hour, copy the audit logs out of the project. Everything else comes after those two steps.

Which logs show what an attacker did in Google Cloud?

Cloud Audit Logs. Admin Activity logs are always on and show configuration changes (IAM, VMs, sinks). Data Access logs show reads of data but are off by default for most services. VPC Flow Logs show network traffic of VMs if they were enabled on the subnet.

How far back can I investigate?

Admin Activity and System Event logs are kept 400 days in the _Required bucket. Data Access and Policy Denied logs go to the _Default bucket, kept 30 days by default. Older data only exists if a sink exported it.

Further reading

Related articles

This tool is not affiliated with, endorsed by or sponsored by Google LLC. Google Cloud and Google Cloud Platform are trademarks of Google LLC. Other names are trademarks of their respective owners.