aws-sf-execute-as-via-definition

Modify a state machine's ASL definition (states:UpdateStateMachine), then trigger an execution to run arbitrary AWS SDK Task states as the execution role.

derived aws emits CanExecuteAs

match

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

{'principal': None} CanModifyCode {'state_machine': None} {'state_machine': None} ExecutesAs {'role': None}

where

node_type(?state_machine) == Workflow

optional

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

{'principal': None} CanInvoke {'state_machine': None}

emit

source typeIdentity
target typeMachineIdentity
source?principal
target?role
permissionsstates:UpdateStateMachine states:StartExecution?
conditionstrigger_exists
state logicACTIVE when the principal can both modify the definition AND invoke/trigger the state machine (matched(optional[0]) — states:StartExecution — OR an existing EventBridge rule or Scheduler is already bound to the state machine and is ENABLED). CONDITIONAL(trigger_exists) when the definition can be modified but no run path is established (no StartExecution permission and no existing active trigger). Never stronger than the contributing CanModifyCode and ExecutesAs edges; BLOCKED if either is BLOCKED (SCP/ permission boundary denial of states:UpdateStateMachine or the execution role is deleted/disabled).

Narrative

{principal.name} can replace the definition of state machine {state_machine.name} (states:UpdateStateMachine) to include Task states that call arbitrary AWS services as {role.name}; triggering an execution (direct StartExecution or an existing EventBridge trigger) then runs those Task states as {role.name}.

Raw rule rules/derived/aws/stepfunctions.yaml

id: aws-sf-execute-as-via-definition
emits: CanExecuteAs
description: Modify a state machine's ASL definition (states:UpdateStateMachine), then trigger an execution
  to run arbitrary AWS SDK Task states as the execution role.
match:
- - principal: null
  - CanModifyCode
  - state_machine: null
- - state_machine: null
  - ExecutesAs
  - role: null
where:
- node_type(?state_machine) == Workflow
optional:
- - principal: null
  - CanInvoke
  - state_machine: null
emit:
  source_type: Identity
  target_type: MachineIdentity
  source: ?principal
  target: ?role
  permissions:
  - states:UpdateStateMachine
  - states:StartExecution?
  conditions:
  - trigger_exists
  state_logic: "ACTIVE when the principal can both modify the definition AND invoke/trigger the state\
    \ machine (matched(optional[0]) \u2014 states:StartExecution \u2014 OR an existing EventBridge rule\
    \ or Scheduler is already bound to the state machine and is ENABLED). CONDITIONAL(trigger_exists)\
    \ when the definition can be modified but no run path is established (no StartExecution permission\
    \ and no existing active trigger). Never stronger than the contributing CanModifyCode and ExecutesAs\
    \ edges; BLOCKED if either is BLOCKED (SCP/ permission boundary denial of states:UpdateStateMachine\
    \ or the execution role is deleted/disabled)."
  confidence: min(contributing_confidences) * 0.95
  derived_from:
  - <CanModifyCode edge_id on ?state_machine>
  - <ExecutesAs edge_id ?state_machine -> ?role>
  - <CanInvoke edge_id?>
  false_positive_note: "Only ACTIVE when a run path exists: the attacker can StartExecution (CanInvoke\
    \ matched) OR a live EventBridge rule / Scheduler schedule is already bound to the state machine (trigger_exists\
    \ confirmed). A modified definition with no trigger is CONDITIONAL(trigger_exists). Do NOT emit ACTIVE\
    \ for a state machine that has no active triggers and whose principal lacks states:StartExecution.\
    \ Dedupes with can-execute-as execute-as-via-code-modify on (CanExecuteAs, ?principal, ?role): this\
    \ rule provides the Workflow-typed framing with Step Functions permissions; do not double-count weight\
    \ where both fire. The escalation consequence (role more privileged than ?principal) is produced by\
    \ can-control escalate-via-execute-as \u2014 cite, do not re-derive."
  narrative: '{principal.name} can replace the definition of state machine {state_machine.name} (states:UpdateStateMachine)
    to include Task states that call arbitrary AWS services as {role.name}; triggering an execution (direct
    StartExecution or an existing EventBridge trigger) then runs those Task states as {role.name}.'
move · open · esc close