93%
of GCP breaches involve misconfigured IAM or service account key exposure
68%
of GCP projects have at least one service account with Owner or Editor role
40%
of GCP data exfiltration attempts are stopped by VPC Service Controls perimeters
3x
more likely to detect credential misuse when Cloud Data Access logs are enabled

SponsoredRetool

Retool's new app builder is where AI-generated code ships safely

Building apps with AI is easy. Getting them to production safely is another story.

Start building for free today

Google Cloud Platform has a security model that differs substantially from AWS and Azure, and most publicly available hardening guidance treats all three as interchangeable. They are not. GCP's organization hierarchy, its constraint-based policy system, and its reliance on service accounts as the primary identity primitive require a distinct approach. The controls that matter most in GCP are not simply renamed versions of AWS security groups and IAM policies. Understanding where GCP's model is architecturally different from the others is the prerequisite for hardening it effectively. This guide covers the GCP-specific controls that reduce attack surface in production environments: organization policies that enforce guardrails at scale, VPC Service Controls that prevent data exfiltration even with valid credentials, workload identity federation that eliminates the service account key risk, and the Cloud Audit Log queries that surface credential misuse before it becomes a full breach.

GCP's Security Model: Organization Hierarchy and the Constraint System

GCP organizes resources in a three-level hierarchy: organization at the top, folders in the middle, and projects at the bottom. IAM policies, organization policies, and billing configurations inherit downward through this hierarchy, which means that controls applied at the organization level apply to every folder and project beneath it. This is architecturally different from AWS accounts, where each account is effectively isolated and cross-account guardrails require AWS Organizations SCPs applied manually. In GCP, a single organization policy constraint applied at the org root propagates to every resource in the environment automatically.

Organization policies use a constraint system rather than resource-level permissions. A constraint like compute.requireOsLogin does not grant or deny a specific permission; it enforces a specific configuration requirement across all projects in scope. When you set compute.requireOsLogin to true at the organization level, no project in that organization can create VM instances that allow SSH key-based login instead of OS Login. The enforcement is declarative and automatic, which means there is no per-project action required when new projects are created. This is the most scalable form of security control in GCP and the one most commonly underused.

Service accounts are GCP's primary identity primitive for non-human workloads, and their behavior differs meaningfully from AWS IAM roles. In AWS, a role is assumed temporarily and the credentials expire. In GCP, a service account is a persistent identity that can hold permanent credentials in the form of service account keys, which are JSON files containing a private key that never expire by default. This creates a class of credential risk that does not have a direct AWS equivalent: a service account key exfiltrated from a developer laptop, a CI/CD system, or a container image provides persistent, unrevoked access to whatever permissions that service account holds until someone explicitly rotates or deletes the key. Understanding this distinction drives most of the hardening recommendations in this guide.

Subscribe to unlock Remediation & Mitigation steps

Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.

Organization Policies: The Constraints That Matter

Organization policy constraints are the highest-leverage hardening control in GCP because they are enforced automatically across new resources without per-project action. The most impactful constraints to configure at the organization level fall into four categories: compute instance behavior, service account management, network controls, and resource location.

For compute instances, compute.requireOsLogin is the single most important constraint. When set to true, it disables the ability to use project-level or instance-level SSH public keys for authentication, forcing all SSH access to go through OS Login, which ties SSH access to IAM identities and enables centralized revocation. Without this constraint, a developer can add their personal SSH key to a VM instance or to the project metadata and retain access indefinitely even after their IAM account is removed. compute.disableSerialPortAccess prevents access to VM serial ports, which can be used to interact with an instance even when SSH is blocked. This is a legitimate troubleshooting path that attackers also exploit when other access methods fail.

For service accounts, iam.disableServiceAccountKeyCreation is the constraint that enforces the shift to workload identity federation. When enabled, it prevents any principal in the organization from creating downloadable JSON key files for service accounts. This is a breaking change for teams that have not yet migrated to workload identity federation or impersonation-based authentication, so it requires planning before enforcement. iam.disableServiceAccountKeyUpload prevents uploading external key material to service accounts. iam.restrictCrossProjectServiceAccountLentiality prevents service accounts from one project from being granted roles in another project, which limits lateral movement paths.

For network controls, compute.restrictCloudBuildServiceAccount prevents the default Cloud Build service account from being used, forcing teams to create purpose-built service accounts with minimal permissions for CI/CD pipelines. compute.vmExternalIpAccess restricts which VM instances can have external IP addresses, enforcing a model where internet-facing access goes through load balancers or Cloud NAT rather than direct instance IPs. compute.restrictVpcPeering can limit which VPC networks are permitted to peer with each other, preventing uncontrolled connectivity between production and development environments.

Subscribe to unlock Remediation & Mitigation steps

Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.

Free daily briefing

Briefings like this, every morning before 9am.

Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.

Service Account Hygiene: Eliminating the Key Risk

Service account keys are GCP's most exploited credential type. A key is a JSON file containing a private RSA key associated with a service account identity. Keys do not expire by default, are valid from any IP address, and authenticate without any network-based controls. When a key is created, it is downloadable exactly once from the Cloud Console or API, but the key itself can be stored and reused indefinitely. Keys embedded in container images, committed to source repositories, or stored in insecure CI/CD environment variables represent a persistent, high-value target.

The audit query to find all active service account keys across an organization uses the Cloud Asset Inventory API. Running gcloud asset search-all-resources --asset-types='iam.googleapis.com/ServiceAccountKey' --scope='organizations/ORG_ID' returns all active keys across all projects. Combined with filtering on keyType=USER_MANAGED to exclude system-managed keys, this query surfaces every developer-created key in the environment. The output should show zero user-managed keys in a well-hardened environment, with every workload using workload identity federation or short-lived credentials via the impersonation API instead.

Workload identity federation is the replacement for service account keys in every context where the workload runs outside of GCP. Instead of downloading a key file, an external workload (GitHub Actions, AWS Lambda, a Jenkins pipeline) presents its own identity token from its native identity provider. GCP's workload identity federation validates that token against a configured provider and exchanges it for a short-lived GCP access token. The credentials last one hour, are scoped to specific operations, and cannot be replayed after expiry. For GitHub Actions, this means adding an OIDC provider pointing to token.actions.githubusercontent.com and granting the repository's identity the necessary IAM role. No JSON key file is created, stored, or at risk of exposure.

For workloads that run on GCP itself (Compute Engine, Cloud Run, GKE), the correct pattern is attached service accounts and the metadata server, not key files. A VM or container with an attached service account automatically receives short-lived access tokens from the metadata server at 169.254.169.254/computeMetadata/v1/instance/service-accounts/. The token refreshes every hour without any application-side logic. Workloads should use Application Default Credentials (ADC) so they pick up metadata server credentials automatically in production and developer credentials locally, without code changes between environments.

Subscribe to unlock Remediation & Mitigation steps

Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.

VPC Service Controls: Stopping Exfiltration Even With Valid Credentials

VPC Service Controls (VPC-SC) is GCP's mechanism for creating a logical perimeter around GCP API services that prevents data from leaving the perimeter even when the requesting principal has valid credentials and appropriate IAM permissions. Without VPC-SC, an attacker who compromises a service account with BigQuery Data Viewer permissions can run bq extract to copy an entire dataset to a Cloud Storage bucket they control in a different project or organization. VPC-SC prevents that export from completing because the destination bucket is outside the defined perimeter.

A VPC-SC perimeter specifies which projects are inside the boundary and which GCP APIs are restricted by the perimeter. When a request hits a restricted API, VPC-SC evaluates whether the request originates from inside the perimeter (an allowed VPC network, an access level condition, or an identity inside the perimeter). Requests that originate outside the perimeter to access resources inside it are denied, even if the requesting identity has the correct IAM role. This is the key property: VPC-SC operates below IAM and can block actions that IAM would otherwise allow.

Deploying VPC-SC requires planning because it breaks legitimate cross-project access patterns that teams may not be aware of. The recommended approach is to start in dry-run mode, which logs what would be denied without actually denying it. Dry-run logs appear in Cloud Logging under the cloudasset.googleapis.com/policy_violation log name. After reviewing dry-run violations for one to two weeks and adding access levels or ingress rules to accommodate legitimate patterns, switch the perimeter to enforced mode. Access levels allow VPC-SC to grant perimeter access based on conditions like originating IP range, device policy compliance, or user identity, which handles the cases where humans outside the VPC network need access to perimeter-protected resources.

For storage exfiltration specifically, the most important services to include in a VPC-SC perimeter are storage.googleapis.com (Cloud Storage), bigquery.googleapis.com (BigQuery), cloudkms.googleapis.com (Cloud KMS), and secretmanager.googleapis.com (Secret Manager). These are the services most commonly targeted in data exfiltration scenarios. A perimeter that restricts only these four services eliminates the most common exfiltration paths while minimizing the blast radius of perimeter misconfiguration.

Subscribe to unlock Remediation & Mitigation steps

Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.

IAM Least Privilege: Roles, Boundaries, and Binding Hygiene

GCP IAM has three categories of roles: primitive roles (Owner, Editor, Viewer), predefined roles (purpose-built roles like roles/storage.objectViewer), and custom roles (manually defined permission sets). Primitive roles are legacy constructs that predate predefined roles and should be treated as off-limits for any production workload. roles/owner grants the ability to set IAM policies, which means any account with Owner can grant itself any permission in the project. roles/editor grants write access to nearly every resource type in a project. Neither role has a place in a hardened environment. The audit query gcloud projects get-iam-policy PROJECT_ID --format=json | jq '.bindings[] | select(.role == "roles/owner" or .role == "roles/editor")' surfaces all Owner and Editor bindings that require remediation.

Predefined roles provide purpose-built permission sets for each service. For storage access, the difference between roles/storage.admin (full control including bucket policy changes), roles/storage.objectAdmin (object CRUD but no policy changes), and roles/storage.objectViewer (read-only) represents a significant attack surface difference. When assigning roles to service accounts, the practice is to find the most restrictive predefined role that enables the required functionality and assign that. If no predefined role fits precisely, a custom role built from individual permissions is the correct path rather than escalating to a broader predefined role.

Binding hygiene involves three ongoing practices. First, IAM Recommender generates role recommendations based on actual API call history for each principal. A service account that was granted roles/storage.admin but only ever calls storage.objects.get will receive a recommendation to downgrade to roles/storage.objectViewer. IAM Recommender recommendations should be reviewed and applied on a regular cycle, ideally monthly. Second, IAM bindings at the organization and folder level deserve special scrutiny because they grant access to all projects below. A principal with roles/editor at the folder level has write access to every project in that folder, which is rarely the intent. Third, IAM conditions can restrict bindings to specific resource names, resource types, or time windows, which enables time-limited access for contractors or environment-scoped access for service accounts.

Subscribe to unlock Remediation & Mitigation steps

Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.

Cloud Audit Logs: What to Enable and What to Watch

GCP Cloud Audit Logs records who did what, where, and when across GCP services. There are four log types: Admin Activity, Data Access, System Event, and Policy Denied. Admin Activity logs capture administrative operations (creating or deleting resources, modifying IAM policies, changing configuration) and are always enabled with no ability to disable them. System Event logs capture GCP-initiated actions like live migration events. These two are free and always available.

Data Access logs are the critical missing piece in most GCP environments. They capture read access to resource configurations and metadata (DATA_READ) and read/write access to user-provided data (DATA_WRITE and DATA_READ on resource data). Data Access logs are disabled by default because they can generate enormous log volume and associated Cloud Logging costs for high-traffic environments. The correct approach is not to enable all Data Access logs for all services universally but to enable them selectively for high-risk services. The minimum set that covers the most important exfiltration and access paths includes: cloudkms.googleapis.com (DATA_READ and DATA_WRITE for all key operations), secretmanager.googleapis.com (DATA_READ to capture every secret access), storage.googleapis.com (DATA_READ and DATA_WRITE for critical buckets), and iam.googleapis.com (DATA_READ to capture policy reads and token generation).

Enabling Data Access logs for Secret Manager is especially important because secret access leaves no trace in any other log type. Every time a workload or user calls secretmanager.googleapis.com.accessSecretVersion, that call appears in Data Access logs with the full resource name, caller identity, and source IP. Without Data Access logs enabled, a compromised workload that reads every secret in a project leaves no evidence trail. The audit query to surface unusual secret access in Cloud Logging is: resource.type="secretmanager.googleapis.com/SecretVersion" protoPayload.methodName="google.cloud.secretmanager.v1.SecretManagerService.AccessSecretVersion" filtered to exclude known service accounts and grouped by caller identity to surface anomalies.

For IAM-related detection, the most valuable log entries are SetIamPolicy calls (indicating permission changes), GenerateAccessToken calls (indicating service account impersonation), and SignBlob/SignJwt calls (indicating credential generation). These appear in Admin Activity logs and do not require Data Access log enablement. A detection rule that alerts on any SetIamPolicy call that grants primitive roles (Owner or Editor) or grants any role to an external identity (one outside the organization domain) covers the most common privilege escalation paths in GCP.

Subscribe to unlock Remediation & Mitigation steps

Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.

Security Command Center and Compute Hardening

Security Command Center (SCC) is GCP's native CSPM and threat detection service. The Standard tier is free and provides basic vulnerability findings and some security health analytics. The Premium tier adds Event Threat Detection (real-time log-based detection), Container Threat Detection (kernel-level GKE threat detection), Virtual Machine Threat Detection, and Web Security Scanner for App Engine and Cloud Run applications. For most organizations with production workloads on GCP, the Premium tier is the right default because Event Threat Detection covers the log-based attack patterns that would otherwise require a SIEM with custom rules.

SCC finding categories that map to real attack paths and should be treated as P1 remediation items include: OPEN_FIREWALL (VPC firewall rules allowing 0.0.0.0/0 inbound on sensitive ports), PUBLIC_BUCKET_ACL (Cloud Storage buckets with public access), KMS_KEY_ROTATED (encryption keys not rotated in over 90 days), SERVICE_ACCOUNT_KEY_NOT_ROTATED (user-managed service account keys older than 90 days), and ADMIN_SERVICE_ACCOUNT (service accounts with Owner, Editor, or Security Admin roles). Event Threat Detection findings in the CREDENTIAL_ACCESS category, including SERVICE_ACCOUNT_SELF_INVESTIGATION and ANOMALOUS_GRANT, indicate active exploitation attempts and require immediate investigation.

For Compute Engine hardening, Shielded VMs provide integrity verification for the VM boot process, protecting against bootkit and rootkit persistence techniques. Shielded VMs include Secure Boot (rejects unsigned bootloaders), vTPM (virtual Trusted Platform Module for measured boot), and Integrity Monitoring (compares the current boot measurement against a known-good baseline). Enabling Shielded VM at the organization policy level via compute.requireShieldedVm ensures all new VMs are created with these protections. The metadata server, accessible at 169.254.169.254 from within a VM, should be protected by blocking access from containers and non-GCP processes where possible, and by using the v1beta1 metadata endpoint that requires a Metadata-Flavor: Google header, which prevents SSRF-based credential theft from naive SSRF vulnerabilities that do not set custom headers.

For GKE specifically, Workload Identity for GKE is the mechanism that allows pods to call GCP APIs as specific service accounts without mounting key files. Each Kubernetes service account is annotated to link it to a GCP service account, and the GKE metadata server intercepts credential requests from pods and returns short-lived tokens for the linked GCP service account. Binary Authorization enforces that only container images signed by approved authorities can be deployed to a cluster, which prevents deployment of unauthorized or tampered images. Private clusters eliminate the control plane's public endpoint and route all API server traffic through Private Service Connect, removing the cluster API server from the public internet entirely.

Subscribe to unlock Remediation & Mitigation steps

Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.

The bottom line

GCP's security model rewards teams that apply controls at the organization level and build outward rather than hardening individual projects one at a time. The highest-leverage starting point is a set of organization policy constraints that establish baseline behavior across every project automatically: requireOsLogin, disableServiceAccountKeyCreation, restrictCloudBuildServiceAccount. From there, enabling Data Access logs for Secret Manager and Cloud KMS fills the most dangerous visibility gaps. VPC Service Controls in dry-run mode for one to two weeks, followed by enforcement, closes the exfiltration paths that IAM alone cannot block. IAM Recommender applied monthly keeps permissions from drifting toward over-privilege as workloads evolve. These controls together address the most common GCP breach patterns without requiring per-project manual work on an ongoing basis.

Frequently asked questions

What is the difference between IAM policies and organization policies in GCP?

IAM policies control who can perform what actions on which resources. Organization policies control what configurations are allowed for resources regardless of who is making the request. IAM policies are additive and grant permissions. Organization policies are restrictive and deny certain configurations at the resource level, enforcing guardrails that IAM cannot. A principal with Owner on a project cannot override an organization policy constraint applied at the org or folder level above that project.

Why are service account keys considered GCP's highest credential risk?

Service account keys are JSON files containing a private RSA key that authenticates as the service account from any IP address, at any time, with no expiry by default. Unlike access tokens (which last one hour) or IAM role assumptions, a key file provides permanent access until explicitly deleted or rotated. Keys are frequently embedded in container images, committed to source repositories, or stored in CI/CD systems, creating persistent high-value targets. Workload identity federation eliminates key files by replacing them with short-lived OIDC token exchange.

Does VPC Service Controls replace IAM, or do both need to be configured?

VPC Service Controls and IAM are complementary layers that serve different purposes. IAM controls who has permission to perform actions. VPC Service Controls controls from where those actions can be performed, regardless of IAM permissions. A request that passes IAM checks but originates from outside the VPC-SC perimeter is still denied. Both layers should be configured: IAM enforces least privilege on identities, and VPC-SC enforces network-based access boundaries that prevent exfiltration even from compromised identities with valid permissions.

How do I enable Data Access logs for Secret Manager without incurring excessive logging costs?

Enable Data Access logs selectively per service rather than organization-wide. In the Cloud Console under IAM & Admin > Audit Logs, select Secret Manager and enable DATA_READ and DATA_WRITE. For Cloud KMS, do the same. For Cloud Storage, enable Data Access logs only on specific high-sensitivity buckets using bucket-level audit log configuration rather than the global setting. Avoid enabling DATA_READ for services like Cloud Storage at the organization level where object read volume is high; this generates logs proportional to every object read and can significantly increase logging costs.

What is the minimum set of Security Command Center findings that should trigger immediate remediation?

Five SCC finding categories require immediate remediation regardless of other priorities: PUBLIC_BUCKET_ACL (Cloud Storage buckets with public access enabled), OPEN_FIREWALL for ports 22, 3389, 1433, 3306, and 5432 from 0.0.0.0/0, SERVICE_ACCOUNT_ADMIN_PRIVILEGES (service accounts with Owner or Editor roles), any Event Threat Detection finding in the CREDENTIAL_ACCESS category (active exploitation indicators), and OVER_PRIVILEGED_SERVICE_ACCOUNT_USER (humans with Service Account User on overprivileged service accounts). These five categories represent the most common pre-breach and active-breach indicators in GCP environments.

Sources & references

  1. Google Cloud Security Foundations Blueprint
  2. NIST SP 800-190 Container Security
  3. CIS Google Cloud Platform Foundation Benchmark
  4. Google Cloud Audit Logs Documentation
  5. VPC Service Controls Overview

Free resources

25
Free download

Critical CVE Reference Card 2025–2026

25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.

No spam. Unsubscribe anytime.

Free download

Ransomware Incident Response Playbook

Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.

No spam. Unsubscribe anytime.

Free newsletter

Get threat intel before your inbox does.

50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.

Unsubscribe anytime. We never sell your data.

Eric Bang
Author

Founder & Cybersecurity Evangelist, Decryption Digest

Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.

Black Hat Giveaway

Win a $2,495 Black Hat pass.

Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.

Joins Decryption Digest daily briefing. Unsubscribe anytime.

Giveaway: Black Hat USA 2026 Full-Access Pass ($2,495 value)

Details →
Daily Briefing

Subscribe to enter the giveaway

Every subscriber is automatically entered. You also get daily threat intel every morning: zero-days, ransomware, and nation-state campaigns. Free. No spam.

Already subscribed? You're already entered.

Giveaway

Win a $2,495 Black Hat USA 2026 pass.