gcp-bigquery-explicit-executes-as

A scheduled query with serviceAccountName set runs as that SA; zero-cost fact enabling cicd-chains derivation.

explicit gcp emits ExecutesAs

match (record)

{ "field": "serviceAccountName", "resource_type": "google.bigquery.datatransfer.TransferConfig" }

where

serviceAccountName is non-empty

emit

source typeMessaging
target typeIdentity
source<TransferConfig node>
target<service account named in serviceAccountName>
state logicACTIVE when serviceAccountName is set and the SA exists; UNKNOWN when the SA cannot be resolved.

Narrative

Scheduled query {transferconfig.name} executes as service account {sa.name} (serviceAccountName field); its SQL runs with {sa.name}'s data-plane IAM grants.

Raw rule rules/explicit/gcp/bigquery.yaml

id: gcp-bigquery-explicit-executes-as
emits: ExecutesAs
description: A scheduled query with serviceAccountName set runs as that SA; zero-cost fact enabling cicd-chains
  derivation.
match_record:
  resource_type: google.bigquery.datatransfer.TransferConfig
  field: serviceAccountName
where:
- serviceAccountName is non-empty
emit:
  source_type: Messaging
  target_type: Identity
  source: <TransferConfig node>
  target: <service account named in serviceAccountName>
  permissions: []
  conditions: []
  state_logic: ACTIVE when serviceAccountName is set and the SA exists; UNKNOWN when the SA cannot be
    resolved.
  false_positive_note: "When serviceAccountName is NOT set, the scheduled query runs as the creating user's\
    \ delegated credentials (OAuth refresh token stored server-side by Google). Do NOT emit ExecutesAs\
    \ to a service account when the field is absent. When set, the BigQuery Data Transfer Service executes\
    \ server-side using the SA; the attacker's SQL runs under the SA's data-plane permissions. The SA\
    \ token is NOT accessible via metadata server or any API call \u2014 do not emit ExposesCredential(TransferConfig\
    \ -> SA)."
  narrative: Scheduled query {transferconfig.name} executes as service account {sa.name} (serviceAccountName
    field); its SQL runs with {sa.name}'s data-plane IAM grants.
  derived_from:
  - google.bigquery.datatransfer.TransferConfig.serviceAccountName
  api_source: bigquery.projects.transferConfigs.list + bigquery.projects.transferConfigs.get
  evidence_field: serviceAccountName
move · open · esc close