gcp-gcf-execute-as-via-code

Modify function source + (invoke/call OR existing trigger) + ExecutesAs.

derived gcp emits CanExecuteAs

match

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

{'principal': None} CanModifyCode {'function': None} {'function': None} ExecutesAs {'sa': None}

where

node_type(?function) == ServerlessFunction ?sa.privilege_level >= ?principal.privilege_level

optional

Present → upgrade the emitted state; absent → downgrade (not a hard requirement).

{'principal': None} CanInvoke {'function': None}

emit

source typeIdentity
target typeIdentity
source<principal>
target<runtime service account>
permissionscloudfunctions.functions.sourceCodeSet
state logicACTIVE if matched(optional[0]) or trigger_exists(?function) else CONDITIONAL(trigger_exists). The CanInvoke that satisfies optional[0] is gcp-gcf-invoke for 1st-gen or gcp-gcf-invoke-run (run.routes.invoke on the backing Cloud Run service) for 2nd-gen.

Narrative

{principal.name} can replace the source of {function.name} (cloudfunctions.functions.sourceCodeSet) and run it, executing as {sa.name}.

Raw rule rules/derived/gcp/gcf.yaml

id: gcp-gcf-execute-as-via-code
emits: CanExecuteAs
description: Modify function source + (invoke/call OR existing trigger) + ExecutesAs.
match:
- - principal: null
  - CanModifyCode
  - function: null
- - function: null
  - ExecutesAs
  - sa: null
optional:
- - principal: null
  - CanInvoke
  - function: null
where:
- node_type(?function) == ServerlessFunction
- ?sa.privilege_level >= ?principal.privilege_level
emit:
  source_type: Identity
  target_type: Identity
  source: <principal>
  target: <runtime service account>
  permissions:
  - cloudfunctions.functions.sourceCodeSet
  state_logic: ACTIVE if matched(optional[0]) or trigger_exists(?function) else CONDITIONAL(trigger_exists).
    The CanInvoke that satisfies optional[0] is gcp-gcf-invoke for 1st-gen or gcp-gcf-invoke-run (run.routes.invoke
    on the backing Cloud Run service) for 2nd-gen.
  conditions_from:
  - function: null
  - sa: null
  false_positive_note: 'Without invoke/call (1st-gen: cloudfunctions.functions.invoke/.call; 2nd-gen:
    run.routes.invoke on the backing Cloud Run service) AND without an existing event trigger -> CONDITIONAL(trigger_exists),
    not ACTIVE. Only escalation when SA privilege exceeds caller''s (default appspot editor SA qualifies).'
  narrative: '{principal.name} can replace the source of {function.name} (cloudfunctions.functions.sourceCodeSet)
    and run it, executing as {sa.name}.'
move · open · esc close