GCP service accounts holding Owner, Editor or any role ending in admin
What does ZopNight detect here?
GCP service accounts granted `roles/owner`, `roles/editor` or any role whose name ends in admin, such as `roles/storage.admin` or `roles/compute.networkAdmin`, hand an attacker broad control if the account's credentials leak. ZopNight flags every such service account as a high-severity finding, with no dollar saving attached.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-130 |
| Category | compliance |
| Severity | high |
| Metric | none — pure configuration read |
| Threshold | service account holds roles/owner, roles/editor or any role ending in admin |
| Source | ZopNight |
| Permissions used | resourcemanager.projects.getIamPolicy · iam.serviceAccounts.list |
Where it applies
Why a service account is the worst place for an admin role
A service account is an identity used by software, and software leaks credentials in ways people do not: a key file committed to a repository, a token readable from a compromised VM, an impersonation chain across projects. Google’s service account best practices spend most of their length on those threats.
Admin roles turn a leak into a takeover. Basic roles roles/owner and roles/editor apply to the
whole project. Predefined roles/*.admin roles, like roles/storage.admin or roles/pubsub.admin,
are limited to one service but give full control within it. A workload that uploads files needs to
create objects, not administer every bucket.
Some of this is inherited, not chosen. Google notes that default service accounts may be granted Editor automatically when their API is enabled, depending on organization policy, and that the grant is for convenience and not needed for the services to work.
Listing service accounts with admin roles
gcloud projects get-iam-policy PROJECT_ID \ --flatten=bindings \ --filter="bindings.role=roles/owner OR bindings.role=roles/editor OR bindings.role~admin$" \ --format="value(bindings.role, bindings.members)" | grep serviceAccount:Two things ZopNight checks
- The principal is a service account, identified by its
serviceAccount:prefix. Human users and groups with admin roles are out of scope for this rule. - Among the roles ZopNight read for that service account, at least one is a basic role
(
roles/ownerorroles/editor) or any role whose name ends inadmin, such asroles/storage.admin,roles/compute.networkAdmin,roles/iam.securityAdminor a custom role named that way.
The finding’s description is the same for every account. It explains both scopes, project-wide for
basic roles and one full service for *.admin roles, without saying which role matched.
When a service account is not flagged
Accounts with only narrow predefined or custom roles are silent. If ZopNight has no confirmed admin role recorded for an account, it does not infer one. Viewer is not an admin role and does not trigger this finding; basic-role use across the project, including by users, is covered by GCP IAM Primitive Role in Use.
A compromise multiplier, no saving
There is no saving. The risk is that one leaked credential grants control over a whole project or service, which is the difference between a contained incident and a rebuild.
Cutting a service account down to size
- List what the workload actually calls. Google’s role recommendations show unused permissions.
- Grant narrow predefined roles, for example
roles/storage.objectCreatorinstead ofroles/storage.admin, or a custom role. - Remove the admin binding with
gcloud projects remove-iam-policy-binding PROJECT_ID --member=serviceAccount:SA_EMAIL --role=ROLE. - For new projects, enforce
constraints/iam.automaticIamGrantsForDefaultServiceAccounts. Google notes it does not remove Editor from existing default service accounts, so clean those up by hand.