gcp-kms-selfgrant-to-decrypt
A key manager that can setIamPolicy can self-grant and then decrypt.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
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) — 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)."