gcp-bigquery-explicit-can-modify-code-remote-function

bigquery.routines.update on a REMOTE_FUNCTION Routine lets a principal change the Cloud Run endpoint the function invokes - effectively modifying the code/target at runtime.

explicit gcp emits CanModifyCode

match (effective permission)

{ "action": "bigquery.routines.update", "resource_type": "google.bigquery.Routine" }

where

Routine.routineType == 'REMOTE_FUNCTION' (not a UDF or standard routine) Routine.remoteFunctionOptions.endpoint is set to a Cloud Run service or HTTPS URL

emit

source typeIdentity
target typeMessaging
source<principal>
target<BigQuery Routine (REMOTE_FUNCTION) node>
permissionsbigquery.routines.update
conditionsiam_permission
state logicACTIVE when bigquery.routines.update is confirmed on the Routine and the Routine is of type REMOTE_FUNCTION; CONDITIONAL(iam_permission) when the permission is inherited at project scope but may be scoped away.

Narrative

{principal.name} can modify remote function {routine.name} (bigquery.routines.update), changing its Cloud Run endpoint to an attacker-controlled service. Any query calling this function will POST to the attacker's URL, enabling data exfiltration and lateral movement. The cicd-chains linchpin (cicd-modify-buildspec-executes-as) or can-execute-as linchpin captures downstream CanExecuteAs if the attacker's endpoint itself ExecutesAs a privileged identity.

Raw rule rules/explicit/gcp/bigquery.yaml

id: gcp-bigquery-explicit-can-modify-code-remote-function
emits: CanModifyCode
description: "bigquery.routines.update on a REMOTE_FUNCTION Routine lets a principal change the Cloud\
  \ Run endpoint the function invokes \u2014 effectively modifying the code/target at runtime."
match_effective_permission:
  action: bigquery.routines.update
  resource_type: google.bigquery.Routine
where:
- Routine.routineType == 'REMOTE_FUNCTION' (not a UDF or standard routine)
- Routine.remoteFunctionOptions.endpoint is set to a Cloud Run service or HTTPS URL
emit:
  source_type: Identity
  target_type: Messaging
  source: <principal>
  target: <BigQuery Routine (REMOTE_FUNCTION) node>
  permissions:
  - bigquery.routines.update
  conditions:
  - iam_permission
  state_logic: ACTIVE when bigquery.routines.update is confirmed on the Routine and the Routine is of
    type REMOTE_FUNCTION; CONDITIONAL(iam_permission) when the permission is inherited at project scope
    but may be scoped away.
  false_positive_note: "bigquery.routines.update allows modifying the routine definition, including the\
    \ remoteFunctionOptions.endpoint (the Cloud Run URL or HTTPS endpoint). By changing the endpoint to\
    \ an attacker-controlled service, any query calling this remote function will invoke the attacker's\
    \ code with the query's data. This is a cross-service lateral movement vector: if the remote function\
    \ originally called a Cloud Run service (which ExecutesAs a SA), rerouting it to an attacker-controlled\
    \ endpoint bypasses the original SA's trust and access controls. Note: updating a routine of type\
    \ FUNCTION or TABLE_VALUED_FUNCTION (SQL UDFs) also modifies code but does not have external invoke\
    \ implications \u2014 those are pure SQL UDF updates."
  narrative: '{principal.name} can modify remote function {routine.name} (bigquery.routines.update), changing
    its Cloud Run endpoint to an attacker-controlled service. Any query calling this function will POST
    to the attacker''s URL, enabling data exfiltration and lateral movement. The cicd-chains linchpin
    (cicd-modify-buildspec-executes-as) or can-execute-as linchpin captures downstream CanExecuteAs if
    the attacker''s endpoint itself ExecutesAs a privileged identity.'
  derived_from:
  - bigquery.routines.update effective permission on google.bigquery.Routine (REMOTE_FUNCTION)
  api_source: Cloud Asset Inventory analyzeIamPolicy
  evidence_field: bigquery.routines.update effective permission
move · open · esc close