gcp-appengine-execute-as-traffic
Route App Engine traffic to a version that runs as a privileged SA (no invoke perm needed).
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
?instance belongs to a version whose code the principal controls OR an existing exploitable version
?sa.privilege_level >= ?principal.privilege_level
emit
| source type | Identity |
|---|---|
| target type | Identity |
| source | <principal> |
| target | <runtime service account> |
| permissions | appengine.services.update |
| conditions | iam_permission |
| state logic | if an attacker-controlled/weaker version exists to receive traffic (the principal can deploy or already controls one): ACTIVE else: CONDITIONAL(trigger_exists) # traffic routing is inert without a controllable target version |
Narrative
{principal.name} can split App Engine traffic (appengine.services.update) to a controlled version, executing its code as {sa.name}.
Raw rule rules/derived/gcp/appengine.yaml
id: gcp-appengine-execute-as-traffic
emits: CanExecuteAs
description: Route App Engine traffic to a version that runs as a privileged SA (no invoke perm needed).
match:
- - principal: null
- CanModifyConfiguration
- app: null
- - instance: null
- ExecutesAs
- sa: null
where:
- ?instance belongs to a version whose code the principal controls OR an existing exploitable version
- ?sa.privilege_level >= ?principal.privilege_level
emit:
source_type: Identity
target_type: Identity
source: <principal>
target: <runtime service account>
permissions:
- appengine.services.update
state_logic: 'if an attacker-controlled/weaker version exists to receive traffic (the principal can
deploy or already controls one): ACTIVE else: CONDITIONAL(trigger_exists) # traffic routing is inert
without a controllable target version
'
conditions:
- iam_permission
derived_from:
- <CanModifyConfiguration edge_id>
- <ExecutesAs edge_id>
false_positive_note: 'appengine.services.update only routes traffic; execution-as the SA is realized
only when a controllable or exploitable version exists to serve. Without one, downgrade to CONDITIONAL(trigger_exists).
'
narrative: '{principal.name} can split App Engine traffic (appengine.services.update) to a controlled
version, executing its code as {sa.name}.'