gcp-bigtable-set-iam-policy
bigtable.tables.setIamPolicy lets a principal grant any role on the table to any principal (including itself). Self-granting roles/bigtable.user (includes bigtable.tables.readRows + bigtable.tables.mutateRows) yields full data-plane read/write access scoped to that table without project-level IAM change.
match (effective permission)
{
"action": "bigtable.tables.setIamPolicy",
"resource_type": "google.bigtable.admin.v2.Table"
}
emit
| source type | Identity |
|---|---|
| target type | Identity |
| source | <principal> |
| target | <any principal (self-grant or other)> |
| permissions | bigtable.tables.setIamPolicy |
| conditions | iam_permission |
| state logic | ACTIVE when bigtable.tables.setIamPolicy is confirmed as an ACTIVE effective permission on the table, instance, or project scope AND no deny policy or org policy blocks IAM mutations on Bigtable resources; CONDITIONAL(iam_permission) when the effective-permission evaluation is uncertain (e.g. IAM Conditions expression partially unresolved); BLOCKED when a deny policy explicitly denies bigtable.tables.setIamPolicy at the effective scope, or when a VPC-SC perimeter blocks IAM admin API calls (note: IAM calls are not part of the Bigtable service perimeter scope; VPC-SC does NOT block setIamPolicy for bigtable.googleapis.com). |
Narrative
{principal.name} holds bigtable.tables.setIamPolicy on table {table.name} and can grant itself or any principal roles/bigtable.user, gaining bigtable.tables.readRows + bigtable.tables.mutateRows (full data-plane read/write) on {table.name} without modifying project-level IAM.
Raw rule rules/derived/gcp/bigtable.yaml
id: gcp-bigtable-set-iam-policy
emits: CanGrantPermission
description: bigtable.tables.setIamPolicy lets a principal grant any role on the table to any principal
(including itself). Self-granting roles/bigtable.user (includes bigtable.tables.readRows + bigtable.tables.mutateRows)
yields full data-plane read/write access scoped to that table without project-level IAM change.
match_effective_permission:
action: bigtable.tables.setIamPolicy
resource_type: google.bigtable.admin.v2.Table
emit:
source_type: Identity
target_type: Identity
source: <principal>
target: <any principal (self-grant or other)>
permissions:
- bigtable.tables.setIamPolicy
conditions:
- iam_permission
state_logic: 'ACTIVE when bigtable.tables.setIamPolicy is confirmed as an ACTIVE effective permission
on the table, instance, or project scope AND no deny policy or org policy blocks IAM mutations on
Bigtable resources; CONDITIONAL(iam_permission) when the effective-permission evaluation is uncertain
(e.g. IAM Conditions expression partially unresolved); BLOCKED when a deny policy explicitly denies
bigtable.tables.setIamPolicy at the effective scope, or when a VPC-SC perimeter blocks IAM admin API
calls (note: IAM calls are not part of the Bigtable service perimeter scope; VPC-SC does NOT block
setIamPolicy for bigtable.googleapis.com).'
confidence: min(contributing_confidences) * 0.97
derived_from:
- bigtable.tables.setIamPolicy effective permission on Table
false_positive_note: "bigtable.tables.setIamPolicy is present in roles/bigtable.admin (any scope) and\
\ is the per-TABLE IAM mutation action. It allows modifying the Cloud IAM policy of the table resource,\
\ enabling a self-grant of roles/bigtable.user (which includes bigtable.tables.readRows + bigtable.tables.mutateRows\
\ + bigtable.tables.sampleRowKeys). This is a self-escalation path to data access without project\
\ IAM change. Separately, bigtable.instances.setIamPolicy is broader: it modifies IAM at the instance\
\ scope, affecting ALL tables in the instance. Emit a separate CanGrantPermission edge for bigtable.instances.setIamPolicy\
\ with target scoped to the Instance node. Do NOT conflate the two \u2014 table-scope setIamPolicy\
\ does NOT confer instance- level IAM mutation. The human-user minimum-project-role requirement (at\
\ least one project-level Bigtable role) is a UI/console enforcement; the IAM API itself does not\
\ enforce it \u2014 self-granting via setIamPolicy on a table can still succeed for a service account\
\ regardless of project role. Chains to CanReadData(principal, table) via the self-bound roles/bigtable.user,\
\ then to ContainsSecret/CanExfiltrate if the table holds sensitive data."
narrative: '{principal.name} holds bigtable.tables.setIamPolicy on table {table.name} and can grant
itself or any principal roles/bigtable.user, gaining bigtable.tables.readRows + bigtable.tables.mutateRows
(full data-plane read/write) on {table.name} without modifying project-level IAM.'