Skip to main content
compliance · gcp

IAM policies still using the primitive Owner, Editor, or Viewer roles

rule IDs covered
1
severity
high
resource types
all

What does ZopNight detect here?

Primitive roles (roles/owner, roles/editor, roles/viewer) predate GCP's granular IAM and grant project-wide power; Editor alone can modify nearly every resource in the project. ZopNight raises high-severity RC-1250 whenever a discovered role row carries the primitive_role=true label, and the finding closes once no binding uses the 3 roles.

Signal and threshold

How ZopNight evaluates IAM policies still using the primitive Owner, Editor, or Viewer roles.
Field Value
Rule IDsRC-1250
Categorycompliance
Severityhigh
Metricnone — pure configuration read
Sourceiam_primitive_roles.go

Leftovers from before IAM was granular

Owner, Editor, and Viewer are the three “basic” (historically, primitive) roles GCP shipped before per-service IAM existed. They are not scoped to a service, a resource, or a purpose. They are scoped to everything. Editor grants modify access across nearly every API in the project: a CI service account bound as Editor “because deploys kept failing” can also read every Cloud SQL export, rewrite firewall rules, and delete buckets it has never touched. Owner adds IAM administration on top, which turns any compromise into full, self-escalating project control. Viewer is the mildest of the three and still hands out read access to every dataset, secret-adjacent config, and log line in the project at once.

Why the fix is replacement, not narrowing

Unlike a project-level roles/storage.admin grant, which can be re-scoped to a bucket, a primitive role has no smaller version of itself. Remediation is always substitution: work out what the member actually does, then bind the matching predefined roles (roles/cloudsql.client, roles/run.developer, roles/storage.objectViewer, …) or a custom role, and remove the primitive binding. The workable sequence for a live system:

  1. Pull 30–90 days of Cloud Audit Logs for the member to see which APIs it really calls.
  2. Grant the narrow roles alongside the primitive one.
  3. Watch for permission-denied errors, then drop Owner/Editor/Viewer last.

Enumerate the bindings in one command

Terminal window
gcloud projects get-iam-policy PROJECT_ID \
--flatten="bindings[].members" \
--filter="bindings.role:(roles/owner OR roles/editor OR roles/viewer)" \
--format="table(bindings.role, bindings.members)"

Where ZopNight’s signal comes from

The discoverer walks the project IAM policy and emits one synthetic iam-role row per unique role it finds, labeling primitive ones with primitive_role=true; the rule fires purely on that label and abstains for any row without it. Multi-project organizations get one row (and one finding) per project per role, so a fleet-wide Editor habit surfaces as a countable list rather than a single vague warning. Severity is high with $0 attached: nothing about the finding saves money, and no automation edits your policy. Once the last Owner/Editor/Viewer binding is gone, the next discovery cycle stops emitting the label and the finding closes on its own.

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

417 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

417 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·