gcp-kms-selfgrant-to-decrypt

A key manager that can setIamPolicy can self-grant and then decrypt.

derived gcp emits CanDecrypt

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'principal': None} CanGrantPermission {'principal': None}

where

the CanGrantPermission edge derives from cloudkms.cryptoKeys/keyRings.setIamPolicy on ?key CryptoKey.purpose is a decrypt purpose (ENCRYPT_DECRYPT / RAW_ENCRYPT_DECRYPT / ASYMMETRIC_DECRYPT)

emit

target typeEncryptionKey
source<principal>
target<CryptoKey (EncryptionKey subtype)>
permissionscloudkms.cryptoKeys.setIamPolicy cloudkms.cryptoKeyVersions.useToDecrypt
conditionsiam_permission key_permission service_state
state logicPOTENTIAL(key_permission) — the capability requires the attacker to FIRST add a self-binding of roles/cloudkms.cryptoKeyEncrypterDecrypter; becomes ACTIVE once applied AND >=1 version ENABLED. BLOCKED if setIamPolicy or useToDecrypt is denied by IAM deny / VPC-SC.

Narrative

{principal.name} can grant itself decrypt on {key.name} via setIamPolicy, then decrypt with it (potential - requires applying the self-binding).

Raw rule rules/derived/gcp/kms.yaml

id: gcp-kms-selfgrant-to-decrypt
emits: CanDecrypt
description: A key manager that can setIamPolicy can self-grant and then decrypt.
match:
- - principal: null
  - CanGrantPermission
  - principal: null
where:
- the CanGrantPermission edge derives from cloudkms.cryptoKeys/keyRings.setIamPolicy on ?key
- CryptoKey.purpose is a decrypt purpose (ENCRYPT_DECRYPT / RAW_ENCRYPT_DECRYPT / ASYMMETRIC_DECRYPT)
emit:
  target_type: EncryptionKey
  source: <principal>
  target: <CryptoKey (EncryptionKey subtype)>
  permissions:
  - cloudkms.cryptoKeys.setIamPolicy
  - cloudkms.cryptoKeyVersions.useToDecrypt
  conditions:
  - iam_permission
  - key_permission
  - service_state
  state_logic: "POTENTIAL(key_permission) \u2014 the capability requires the attacker to FIRST add a self-binding\
    \ of roles/cloudkms.cryptoKeyEncrypterDecrypter; becomes ACTIVE once applied AND >=1 version ENABLED.\
    \ BLOCKED if setIamPolicy or useToDecrypt is denied by IAM deny / VPC-SC."
  confidence: min(contributing_confidences) * 0.85
  derived_from:
  - <CanGrantPermission (setIamPolicy) edge_id>
  false_positive_note: 'Not yet-active: it models a two-step (self-grant then decrypt) so it MUST be POTENTIAL
    until the binding exists. Only emit when the key is a decrypt-purpose key. Do not double-count with
    gcp-kms-can-decrypt (that rule is for a caller who ALREADY holds useToDecrypt).'
  narrative: "{principal.name} can grant itself decrypt on {key.name} via setIamPolicy, then decrypt with\
    \ it (potential \u2014 requires applying the self-binding)."
move · open · esc close