gcp-secretmanager-read-via-execute-as

A principal that can execute as a workload SA holding versions.access can read the secret.

derived gcp emits CanReadSecret

match

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

{'principal': None} CanExecuteAs {'sa': None}

where

?sa has EFFECTIVE secretmanager.versions.access on ?secret (per-secret or inherited) node_type(?secret) == Secret

emit

source<principal>
target<secret ?sa can access>
permissionssecretmanager.versions.access
conditionsiam_permission resource_policy key_permission
state logicInherits state from the CanExecuteAs input; then ACTIVE if ?sa has versions.access and (non-CMEK OR service agent holds the KMS grant); CONDITIONAL(key_permission) if CMEK and the service-agent grant is unknown; BLOCKED if denied by VPC-SC/IAM deny/KMS.

Narrative

{principal.name}, able to execute as {sa.name}, can read secret {secret.name} because {sa.name} holds secretmanager.versions.access on it.

Raw rule rules/derived/gcp/secretmanager.yaml

id: gcp-secretmanager-read-via-execute-as
emits: CanReadSecret
description: A principal that can execute as a workload SA holding versions.access can read the secret.
match:
- - principal: null
  - CanExecuteAs
  - sa: null
where:
- ?sa has EFFECTIVE secretmanager.versions.access on ?secret (per-secret or inherited)
- node_type(?secret) == Secret
emit:
  source: <principal>
  target: <secret ?sa can access>
  permissions:
  - secretmanager.versions.access
  conditions:
  - iam_permission
  - resource_policy
  - key_permission
  state_logic: Inherits state from the CanExecuteAs input; then ACTIVE if ?sa has versions.access and
    (non-CMEK OR service agent holds the KMS grant); CONDITIONAL(key_permission) if CMEK and the service-agent
    grant is unknown; BLOCKED if denied by VPC-SC/IAM deny/KMS.
  confidence: min(contributing_confidences) * 0.95
  derived_from:
  - <CanExecuteAs edge_id>
  - <?sa secretmanager.versions.access grant>
  false_positive_note: 'Requires the WORKLOAD SA (not the principal directly) to hold versions.access
    on the specific secret. This is the canonical CanExecuteAs -> CanReadSecret -> CredentialsFor completion:
    once code runs as ?sa, it reads the payload from the metadata-derived SA token. Do not emit if ?sa''s
    access is scoped to a different secret.'
  narrative: '{principal.name}, able to execute as {sa.name}, can read secret {secret.name} because {sa.name}
    holds secretmanager.versions.access on it.'
move · open · esc close