aws-sf-execute-as-via-direct-invoke

Directly invoke a state machine (states:StartExecution) with an attacker-supplied input payload to execute as the machine's execution role.

derived aws emits CanExecuteAs

match

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

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

where

node_type(?state_machine) == Workflow

emit

source typeIdentity
target typeMachineIdentity
source?principal
target?role
permissionsstates:StartExecution
conditionsiam_permission
state logicACTIVE when the principal has effective states:StartExecution (or states:StartSyncExecution for Express workflows) on the state machine. The attacker directly invokes an execution with an attacker-controlled input payload — the execution runs the entire workflow definition as ?role, granting the attacker the role's identity for all Task state calls. Inherit state from contributing CanInvoke (not gated on a trigger existing — the principal supplies the trigger directly). BLOCKED if the principal lacks CanInvoke or the role is deleted.

Narrative

{principal.name} can directly start an execution of state machine {state_machine.name} (states:StartExecution), supplying the input payload and causing the entire execution to run as {role.name}.

Raw rule rules/derived/aws/stepfunctions.yaml

id: aws-sf-execute-as-via-direct-invoke
emits: CanExecuteAs
description: Directly invoke a state machine (states:StartExecution) with an attacker-supplied input payload
  to execute as the machine's execution role.
match:
- - principal: null
  - CanInvoke
  - state_machine: null
- - state_machine: null
  - ExecutesAs
  - role: null
where:
- node_type(?state_machine) == Workflow
emit:
  source_type: Identity
  target_type: MachineIdentity
  source: ?principal
  target: ?role
  permissions:
  - states:StartExecution
  conditions:
  - iam_permission
  state_logic: "ACTIVE when the principal has effective states:StartExecution (or states:StartSyncExecution\
    \ for Express workflows) on the state machine. The attacker directly invokes an execution with an\
    \ attacker-controlled input payload \u2014 the execution runs the entire workflow definition as ?role,\
    \ granting the attacker the role's identity for all Task state calls. Inherit state from contributing\
    \ CanInvoke (not gated on a trigger existing \u2014 the principal supplies the trigger directly).\
    \ BLOCKED if the principal lacks CanInvoke or the role is deleted."
  confidence: min(contributing_confidences) * 0.9
  derived_from:
  - <CanInvoke edge_id ?principal -> ?state_machine>
  - <ExecutesAs edge_id ?state_machine -> ?role>
  false_positive_note: "Only ACTIVE for direct invocation (CanInvoke matched); a trigger-based execution\
    \ without direct invocation capability is CONDITIONAL(trigger_exists) and handled by the messaging-chains\
    \ bridge. Dedupes with messaging-trigger-executes-as on (CanExecuteAs, ?principal, ?role) \u2014 this\
    \ rule covers the CanInvoke path, messaging-chains covers the event-trigger path (which targets Messaging\
    \ sources, not the Workflow directly). Do not double-count weight. The identity hierarchy consequence\
    \ (escalation if ?role is more privileged) is produced by can-control \u2014 cite, do not re-derive."
  narrative: '{principal.name} can directly start an execution of state machine {state_machine.name} (states:StartExecution),
    supplying the input payload and causing the entire execution to run as {role.name}.'
move · open · esc close