gcp-secretmanager-impersonate-via-sakey
Reading a secret whose payload is an SA JSON key yields long-lived credentials for that SA.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?sa) ==
ServiceAccount
?secret payload is classified as a service-account JSON key
emit
| source type | Identity |
|---|---|
| source | <principal> |
| target | <service account the key authenticates> |
| permissions | secretmanager.versions.access |
| conditions | iam_permission resource_policy key_permission |
| state logic | Inherits the CanReadSecret state (ACTIVE / CONDITIONAL(key_permission) for CMEK / BLOCKED). ACTIVE read of an SA-key payload = holding that SA's credentials. |
Narrative
{principal.name} can read secret {secret.name}, whose payload is a JSON key for {sa.name}, obtaining long-lived credentials to act as {sa.name}.
Raw rule rules/derived/gcp/secretmanager.yaml
id: gcp-secretmanager-impersonate-via-sakey
emits: CanImpersonate
description: Reading a secret whose payload is an SA JSON key yields long-lived credentials for that SA.
match:
- - principal: null
- CanReadSecret
- secret: null
- - secret: null
- CredentialsFor
- sa: null
where:
- node_type(?sa) == ServiceAccount
- ?secret payload is classified as a service-account JSON key
emit:
source_type: Identity
source: <principal>
target: <service account the key authenticates>
permissions:
- secretmanager.versions.access
conditions:
- iam_permission
- resource_policy
- key_permission
state_logic: Inherits the CanReadSecret state (ACTIVE / CONDITIONAL(key_permission) for CMEK / BLOCKED).
ACTIVE read of an SA-key payload = holding that SA's credentials.
confidence: min(contributing_confidences) * 0.9
derived_from:
- <CanReadSecret edge_id>
- <CredentialsFor edge_id>
false_positive_note: Only when the payload is genuinely an SA JSON key (not a password/token). The key
must not be disabled/deleted at the SA. Same-privilege SAs are lateral, not escalation (see the CanEscalateTo
roll-up). Inherits CMEK gating from the CanReadSecret input.
narrative: '{principal.name} can read secret {secret.name}, whose payload is a JSON key for {sa.name},
obtaining long-lived credentials to act as {sa.name}.'