gcp-bigquery-explicit-executes-as
A scheduled query with serviceAccountName set runs as that SA; zero-cost fact enabling cicd-chains derivation.
match (record)
{
"field": "serviceAccountName",
"resource_type": "google.bigquery.datatransfer.TransferConfig"
}
where
serviceAccountName is non-empty
emit
| source type | Messaging |
|---|---|
| target type | Identity |
| source | <TransferConfig node> |
| target | <service account named in serviceAccountName> |
| state logic | ACTIVE 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