Most Google Cloud compromises are decided by an IAM binding made months earlier: an Editor role on a default service account, a key file in a repository, or Token Creator granted on a whole project. This list ranks the ten Google Cloud IAM mistakes that most often turn one stolen credential into project or organisation control, with how to check for each, how to fix it and which Google controls exist to stop it coming back. Every fix references Google's own IAM, Organization Policy and Policy Intelligence documentation. It is written for Google Cloud platform engineers, cloud security teams and the leads who sign off their access model. The full control set is in the Google Cloud IAM and Service Accounts Guide; this page is the short list of what goes wrong.
The Top 10 at a glance
| # | Mistake | What it enables | Control to check |
|---|---|---|---|
| 1 | Basic roles (Owner, Editor) in production | Thousands of permissions on every resource in scope | Project, folder and organisation allow policies |
| 2 | Default service accounts left with Editor | Any workload on a default VM can change the project | iam.automaticIamGrantsForDefaultServiceAccounts |
| 3 | User-managed service account keys | Long-lived credentials that leak and work from anywhere | iam.disableServiceAccountKeyCreation, key inventory |
| 4 | Impersonation roles granted at project level | Act as every service account in the project | Service Account User and Token Creator bindings |
| 5 | Too many principals who can change IAM | Self-granting any role, silently | Holders of setIamPolicy permissions |
| 6 | Grants at the wrong scope and to individuals | Inherited access far beyond the intended resource | Organisation and folder bindings, user principals |
| 7 | Public and external principals allowed | Data shared with anyone or any Google account | iam.allowedPolicyMemberDomains, allUsers bindings |
| 8 | Cross-project service account chains | Lateral movement from a low-value to a high-value project | iam.disableCrossProjectServiceAccountUsage, lateral movement insights |
| 9 | Standing access that is never pruned | Unused permissions and dormant accounts waiting to be stolen | Role recommendations, IAM Conditions, account disablement |
| 10 | Data Access logs off and IAM changes unwatched | No evidence of impersonation or data reads | Audit log configuration, alerting on SetIamPolicy |
The ranking is our editorial judgement of how directly each mistake leads to compromise. Items 1 to 5 are about how much one identity can do; items 6 to 8 are about how far access spreads; items 9 and 10 decide whether you notice.
1. Basic roles (Owner, Editor) in production
The mistake: Owner or Editor granted to people, groups and service accounts on production projects or, worse, on folders and the organisation node.
Why it matters: Google describes the basic roles as highly permissive, together holding thousands of permissions across all Google Cloud services. Editor can create and delete most resources and, in projects that allow it, create keys for existing service accounts. Owner adds IAM and billing control. Legacy basic roles cannot carry IAM Conditions, so they cannot be time-limited or scoped to a resource name. Owner is also granted automatically to whoever creates a project, so the count grows by default.
How to check: list every binding of roles/owner, roles/editor and roles/viewer across the organisation. Role recommendations raise a HIGH severity insight for basic roles at project, folder or organisation level, and basic role recommendations are free.
How to fix: Google's guidance is not to grant basic roles in production unless there is no alternative. Replace each with the predefined or custom role the recommender proposes, test the change in Policy Simulator, then remove the basic role. Where a broad role is unavoidable, Google recommends the newer Admin, Writer and Reader basic roles over the legacy ones because they support conditions.
2. Default service accounts left with Editor
The mistake: workloads run as the Compute Engine or App Engine default service account, which in older organisations was granted roles/editor on the project automatically.
Why it matters: anything that runs on that VM, including a compromised web application, inherits project-wide write access. The account is shared by every workload that did not specify its own, so audit logs cannot tell them apart.
How to check: find bindings for addresses ending in [email protected] and @appspot.gserviceaccount.com and list which instances, functions and services use them.
How to fix: enforce iam.automaticIamGrantsForDefaultServiceAccounts. It is enforced by default for organisations created on or after 3 May 2024, but it only stops the automatic grant: it does not remove Editor from default accounts that already have it. The managed constraint iam.managed.preventPrivilegedBasicRolesForDefaultServiceAccounts goes further and also blocks later Owner or Editor grants. Then create one dedicated service account per application, attach it, and remove Editor from the default account. Disable rather than delete default accounts: Google notes a deleted default account cannot be recreated.
3. User-managed service account keys
The mistake: JSON key files created for CI pipelines, on-premises jobs and developer laptops, never rotated and copied between systems.
Why it matters: a key works from anywhere until it is deleted, and activity cannot be traced to the person using it. In the Codecov breach, a Google Cloud Storage credential exposed through an error in the company's Docker image build let the attacker alter a script that customers ran in CI, and the tampering went unnoticed for about two months (MITRE ATT&CK T1552.001 Credentials In Files).
How to check: list keys of type USER_MANAGED per service account, with creation date and last authentication from Activity Analyzer and service account insights.
How to fix: Google's key guidance is to avoid user-managed keys and use attached service accounts, impersonation or Workload Identity Federation instead. Enforce iam.disableServiceAccountKeyCreation and iam.disableServiceAccountKeyUpload at the organisation (default for organisations created on or after 3 May 2024) and grant exceptions per project with an owner and an end date. Leave iam.serviceAccountKeyExposureResponse at DISABLE_KEY so Google disables keys it finds leaked publicly; when the constraint is unset it has behaved that way since 16 June 2024, but detection is not guaranteed. See the Google Cloud Service Account Keys Security Guide and the Workload Identity Federation Guide.
4. Impersonation roles granted at project level
The mistake: roles/iam.serviceAccountUser or roles/iam.serviceAccountTokenCreator granted on the project or folder so developers can deploy, instead of on the one service account they need.
Why it matters: a project-level Token Creator binding covers every service account in that project, including the ones with production data access. The permissions behind these roles, iam.serviceAccounts.actAs, iam.serviceAccounts.getAccessToken and iam.serviceAccounts.signBlob, let a user act with the service account's privileges. Google's guidance is plain: do not let users impersonate service accounts that hold more privileges than they do. Google also lists roles/iam.serviceAccountKeyAdmin, roles/iam.serviceAccountAdmin, roles/iam.workloadIdentityUser, Owner and Editor as roles that allow impersonation.
How to check: search allow policies at project and folder scope for those roles, then compare each holder's own privileges with the most privileged service account in scope.
How to fix: grant impersonation on the individual service account resource only. For occasional elevated tasks, use short-lived tokens through the Service Account Credentials API or a just-in-time grant rather than standing access. See the JIT Access Guide.
5. Too many principals who can change IAM
The mistake: Owner, roles/iam.securityAdmin, Project IAM Admin, Folder IAM Admin and roles/iam.serviceAccountAdmin handed out widely because they unblock work.
Why it matters: these roles carry setIamPolicy permissions, so a holder can grant themselves or an attacker-controlled account any role without touching a resource first (ATT&CK T1098.003 Additional Cloud Roles). Google points out that the IAM Admin roles can modify allow policies without direct access to resources, which makes them easy to under-rate in access reviews. On a service account, iam.serviceAccounts.setIamPolicy lets the holder grant themselves impersonation.
How to check: enumerate every principal holding a role that includes resourcemanager.projects.setIamPolicy, resourcemanager.folders.setIamPolicy, resourcemanager.organizations.setIamPolicy or iam.serviceAccounts.setIamPolicy.
How to fix: keep standing IAM administration to a named break-glass group, move other holders to time-bound grants with conditions, and require that changes to production IAM go through infrastructure as code with review. Audit who can change allow policies, as Google's IAM security guidance recommends.
6. Grants at the wrong scope and to individuals
The mistake: roles granted at the organisation or a top folder because it was quicker, and bindings made to individual user accounts rather than groups.
Why it matters: child resources inherit allow policies from their parents, so a folder grant applies to every project beneath it, including ones created later. Individual bindings are scattered across hundreds of policies and survive role changes and departures.
How to check: export organisation and folder allow policies and list every binding below them that names a user: principal directly.
How to fix: grant at the smallest scope that works (Google's example is a single Pub/Sub topic), use organisation-level grants only for principals that genuinely need every project, and bind roles to Google groups so that joiner, mover and leaver changes happen in one place. See the Least Privilege Techniques Guide.
7. Public and external principals allowed
The mistake: allUsers or allAuthenticatedUsers bound to buckets, datasets or services, and personal or partner Google accounts added to production projects.
Why it matters: allUsers means anyone on the internet and allAuthenticatedUsers means anyone with a Google account (ATT&CK T1530 Data from Cloud Storage). Role recommendations rate public bucket or dataset access CRITICAL for this reason. Conditions cannot be applied to these principals, so there is no way to narrow such a grant.
How to check: search all allow policies for allUsers, allAuthenticatedUsers and members outside your domains.
How to fix: enforce domain restricted sharing with iam.allowedPolicyMemberDomains, listing your Google Workspace or Cloud Identity customer ID, or the newer managed constraint iam.managed.allowedPolicyMembers. Organisations created on or after 3 May 2024 have it enforced by default with their own domain. The constraint governs new grants, so remove existing external bindings separately. Where public content is genuinely required, isolate it in a dedicated project with a documented exception (Google notes exceptions need custom organisation policies). See the Google Cloud Organization Policy Guide.
8. Cross-project service account chains
The mistake: a service account in a development or tooling project is allowed to impersonate service accounts in production projects, often through a chain of grants nobody mapped.
Why it matters: Google defines lateral movement as a service account in one project being able to impersonate one in another, which allows chains of impersonation across projects (ATT&CK T1550.001 Application Access Token, T1021.007 Cloud Services). Compromise the weakest project and you reach the strongest.
How to check: use lateral movement insights from Policy Intelligence, which flag service accounts from other projects that hold impersonation permissions such as iam.serviceAccounts.actAs. These insights need the Security Command Center Premium or Enterprise tier.
How to fix: enforce iam.disableCrossProjectServiceAccountUsage where attaching service accounts across projects is not needed, apply the removal recommendations linked to lateral movement insights, and keep production service accounts in projects that only production principals can reach.
9. Standing access that is never pruned
The mistake: permanent grants for project work that ended long ago, contractors who left, and service accounts whose workload was deleted.
Why it matters: every unused permission is attack surface with no business value, and dormant accounts are rarely watched (ATT&CK T1078.004 Cloud Accounts).
How to check: role recommendations compare granted permissions with those used in the last 90 days (30 or 60 days can be set for projects). Note the gaps: grants with conditions get no insights, inactive projects are skipped, and recommendations are never applied automatically.
How to fix: work through recommendations quarterly, use request.time conditions so temporary access expires on its own, and disable single-purpose service accounts when their resource is removed. Disable before you delete: Google warns that a recreated service account with the same name is a new identity and loses its bindings, while disabling and re-enabling keeps them. Remember that a conditional binding does not override an unconditional one for the same role. See the Access Reviews Guide.
10. Data Access logs off and IAM changes unwatched
The mistake: relying on Admin Activity logs alone and never alerting on IAM policy changes.
Why it matters: Data Access audit logs are disabled by default for all services except some BigQuery services. Without DATA_READ logs for the IAM API and the Security Token Service API, impersonation and token creation leave no trace, which Google calls out in its service account guidance. Admin Activity logs are always on and cannot be disabled, so IAM changes are recorded, but recorded is not the same as reviewed.
How to check: read the audit configuration at organisation level and confirm which services have ADMIN_READ, DATA_READ and DATA_WRITE enabled and which principals are exempted.
How to fix: enable Data Access logs for the IAM and Security Token Service APIs and your sensitive data services at organisation level, export to a log bucket in a separate security project for long-term retention, and alert on the events below. See the Google Cloud Audit Logs and Log Sinks Guide.
Detection: what to alert on
| Audit log event | Log type | Mistake it exposes |
|---|---|---|
| SetIamPolicy on organisation, folder or project adding roles/owner, roles/editor or an IAM admin role | Admin Activity | 1, 5, 6 |
| SetIamPolicy adding allUsers, allAuthenticatedUsers or an external domain member | Admin Activity | 7 |
| CreateServiceAccountKey or UploadServiceAccountKey | Admin Activity | 3 |
| SetIamPolicy on a service account granting Service Account User or Token Creator | Admin Activity | 4, 8 |
| GenerateAccessToken or SignBlob by an unexpected principal | Data Access (IAM Credentials API) | 4, 8 |
| Organisation policy changes or deletions for the constraints on this page | Admin Activity | 2, 3, 7, 8 |
| Audit configuration changes removing Data Access logging or adding exemptions | Admin Activity | 10 |
Track five measures: count of basic role bindings in production (target zero for people); user-managed keys outstanding and their median age; impersonation grants made at project or folder scope; principals holding setIamPolicy at organisation or folder level; and the share of HIGH and CRITICAL role recommendations closed within 30 days.
Common failure patterns
- Trusting the 2024 defaults: secure-by-default constraints apply to organisations created on or after 3 May 2024. Older organisations keep their old settings, and even new ones keep any grants made before enforcement.
- Blocking key creation, keeping the keys: the constraint stops new keys; the existing ones still work until deleted.
- Removing Editor from the default account only: the workload then fails and someone grants Editor back. Move the workload to a dedicated account first.
- Deleting service accounts to clean up: a recreated account gets a new identity and bindings break in confusing ways. Disable, wait, then delete.
- Exemptions that last forever: a project excluded from the key creation constraint for a migration is still excluded three years later.
- Reviewing users, not who can change policy: access reviews list who can read data but miss the IAM Admin roles that can grant anything.
Mapping to ATT&CK and NIST
| Item | MITRE ATT&CK | NIST SP 800-53 Rev. 5 | NIST CSF 2.0 |
|---|---|---|---|
| 1, 6. Basic roles and wide scope | T1078.004 | AC-6, AC-2 | PR.AA-05 |
| 2. Default service accounts | T1078.004 | AC-6, CM-6 | PR.PS-01 |
| 3. Service account keys | T1552.001, T1098.001 | IA-5 | PR.AA-01 |
| 4, 8. Impersonation and chains | T1550.001, T1021.007 | AC-6, AC-3 | PR.AA-05 |
| 5. IAM change rights | T1098.003 | AC-6, AC-2 | PR.AA-05 |
| 7. Public principals | T1530 | AC-3 | PR.AA-05 |
| 9. Standing access | T1078.004 | AC-2 | PR.AA-05 |
| 10. Logging | T1685 | AU-2, AU-6 | PR.PS-04, DE.CM-09 |
Where to start
- Week one, read only: export all organisation, folder and project allow policies, list user-managed keys, and record the baseline for the five measures above.
- Week one: remove allUsers and allAuthenticatedUsers from anything that is not deliberately public, and enforce domain restricted sharing (item 7).
- Weeks two to four: enforce the key creation and upload constraints and the default service account constraint at the organisation, with time-limited project exceptions (items 2 and 3).
- Month two: move impersonation grants from project to service account scope and cut setIamPolicy holders to a break-glass group (items 4 and 5).
- Month three: replace basic roles using role recommendations, re-scope folder grants, enable Data Access logs for IAM and STS, and switch on alerts (items 1, 6, 9, 10).
- Test and roll back: simulate each change in Policy Simulator first, change one project or folder at a time, watch for permission denied errors, and roll back by restoring the previous binding from your exported policy or infrastructure as code state.
Small organisations with a handful of projects can do all of this in a month from the console. Large estates should drive it through infrastructure as code and organisation policy so fixes cannot drift back. See the Google Cloud Project Compromise Playbook for what to do if one of these mistakes has already been used.
Practitioner checklist
- No legacy basic roles granted to people in production; remaining broad grants use conditional roles.
- Default service accounts unused by workloads and without Editor; managed default service account constraint enforced.
- Key creation and upload blocked at the organisation; every exception has an owner and an end date.
- Existing user-managed keys inventoried, with a dated plan to replace each with federation or attached accounts.
- Service Account User and Token Creator granted only on individual service accounts.
- setIamPolicy holders at organisation and folder level reviewed monthly and limited to a named group.
- Domain restricted sharing enforced; public resources isolated in dedicated projects.
- Cross-project service account usage blocked where not required; lateral movement insights reviewed.
- Role recommendations reviewed quarterly; temporary grants expire through request.time conditions.
- Data Access logs on for IAM and STS APIs; alerts on SetIamPolicy, key creation and audit configuration changes.
Standards and references
- Google Cloud: Use IAM securely
- Google Cloud: Best practices for using service accounts securely
- Google Cloud: Best practices for managing service account keys
- Google Cloud: Restricting service account usage
- Google Cloud: Restricting identities by domain
- Google Cloud: Role recommendations overview
- Google Cloud: Enable Data Access audit logs
- NIST: SP 800-53 Rev. 5 Security and Privacy Controls
Related NHI Mgmt Group resources: Google Cloud IAM and Service Accounts Guide · Google Cloud Security Checklist · How to inventory Google Cloud service account keys and replace them with federation · Cloud IAM Review Checklist · Top 10 Azure Security Misconfigurations