gcp-firestore-set-iam-self-grant
datastore.databases.setIamPolicy lets a principal grant itself roles/datastore.owner or roles/datastore.viewer on the database, then read or administer all documents.
match (effective permission)
{
"action": "datastore.databases.setIamPolicy",
"resource_type": "google.firestore.Database"
}
emit
| source type | Identity |
|---|---|
| target type | Identity |
| source | <principal> |
| target | <principal (self)> |
| permissions | datastore.databases.setIamPolicy |
| conditions | iam_permission |
| state logic | ACTIVE when setIamPolicy resolves on the database or project scope and no IAM deny or org policy blocks it; BLOCKED when denied. Chains to CanReadData via self-bound roles/datastore.viewer, then to ContainsSecret/CanExfiltrate if the database holds sensitive data or the caller obtains export rights. |
Narrative
{principal.name} can set the IAM policy of Firestore database {database.name} (datastore.databases.setIamPolicy) and grant itself roles/datastore.viewer or roles/datastore.owner, then read all documents in the database.
Raw rule rules/derived/gcp/firestore.yaml
id: gcp-firestore-set-iam-self-grant
emits: CanGrantPermission
description: datastore.databases.setIamPolicy lets a principal grant itself roles/datastore.owner or roles/datastore.viewer
on the database, then read or administer all documents.
match_effective_permission:
action: datastore.databases.setIamPolicy
resource_type: google.firestore.Database
emit:
source_type: Identity
target_type: Identity
source: <principal>
target: <principal (self)>
permissions:
- datastore.databases.setIamPolicy
conditions:
- iam_permission
state_logic: ACTIVE when setIamPolicy resolves on the database or project scope and no IAM deny or org
policy blocks it; BLOCKED when denied. Chains to CanReadData via self-bound roles/datastore.viewer,
then to ContainsSecret/CanExfiltrate if the database holds sensitive data or the caller obtains export
rights.
confidence: min(contributing_confidences) * 0.95
derived_from:
- datastore.databases.setIamPolicy effective permission on Firestore Database
false_positive_note: 'Escalation primitive: a principal that can setIamPolicy on the Firestore database
can grant itself roles/datastore.viewer (read all documents) or roles/datastore.owner (full control
including export). The self-grant produces a CanReadData edge via the derived CanGrantPermission ->
can-control linchpin. For CMEK databases, the service-agent key_permission gate still applies to the
resulting read. Confirm setIamPolicy scope: a project-level grant covers all databases; a database-level
grant covers only that database. Org policy denying IAM mutations at the project level -> BLOCKED.'
narrative: '{principal.name} can set the IAM policy of Firestore database {database.name} (datastore.databases.setIamPolicy)
and grant itself roles/datastore.viewer or roles/datastore.owner, then read all documents in the database.'