aws-codepipeline-trigger-executes-as
StartPipelineExecution over a pipeline whose current definition already runs attacker-influenced code (poisoned artifact, malicious source commit, unpinned dependency) yields execution as the pipeline's service/action role; cicd-chains rule 2 is the canonical collapse (CONDITIONAL).
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
{'principal': None}
CanTrigger {'pipeline': None}
{'pipeline': None} ExecutesAs {'service_role': None}
where
node_type(?pipeline) ==
BuildWorker
?pipeline.provider_type == 'AWS::CodePipeline::Pipeline'
emit
| source type | Identity |
|---|---|
| target type | Identity |
| source | ?principal |
| target | ?service_role |
| permissions | codepipeline:StartPipelineExecution |
| conditions | attacker_influenced_definition |
| state logic | CONDITIONAL(attacker_influenced_definition) by default: triggering runs the CURRENT definition, which yields the service role only if that definition already runs attacker-influenceable code (mutable/unpinned artifact dependency, attacker-authored source branch the trigger builds, already-tampered stage spec, or a build step that runs untrusted PR content). ACTIVE only when attacker influence over the current definition is established (then it collapses to the modify path). A trigger over a fully pinned, reviewed, clean definition stays CONDITIONAL. Inherit weakest with CanTrigger / ExecutesAs contributions. |
Narrative
{principal.name} can start pipeline {pipeline.name} (codepipeline:StartPipelineExecution), which executes as {service_role.name}; if the pipeline's current definition already runs attacker-influenceable code (poisoned dependency, attacker-authored source, tampered stage spec), this run executes as {service_role.name}.
Raw rule rules/derived/aws/codepipeline.yaml
id: aws-codepipeline-trigger-executes-as
emits: CanExecuteAs
description: StartPipelineExecution over a pipeline whose current definition already runs attacker-influenced
code (poisoned artifact, malicious source commit, unpinned dependency) yields execution as the pipeline's
service/action role; cicd-chains rule 2 is the canonical collapse (CONDITIONAL).
match:
- - principal: null
- CanTrigger
- pipeline: null
- - pipeline: null
- ExecutesAs
- service_role: null
where:
- node_type(?pipeline) == BuildWorker
- ?pipeline.provider_type == 'AWS::CodePipeline::Pipeline'
emit:
source_type: Identity
target_type: Identity
source: ?principal
target: ?service_role
permissions:
- codepipeline:StartPipelineExecution
conditions:
- attacker_influenced_definition
state_logic: 'CONDITIONAL(attacker_influenced_definition) by default: triggering runs the CURRENT definition,
which yields the service role only if that definition already runs attacker-influenceable code (mutable/unpinned
artifact dependency, attacker-authored source branch the trigger builds, already-tampered stage spec,
or a build step that runs untrusted PR content). ACTIVE only when attacker influence over the current
definition is established (then it collapses to the modify path). A trigger over a fully pinned, reviewed,
clean definition stays CONDITIONAL. Inherit weakest with CanTrigger / ExecutesAs contributions.'
confidence: min(contributing_confidences) * 0.7
derived_from:
- ?principal CanTrigger ?pipeline
- ?pipeline ExecutesAs ?service_role
- 'cicd-chains: cicd-trigger-runner-executes-as'
false_positive_note: "Strictly weaker than the modify path (0.7 prior). Do NOT emit ACTIVE merely because\
\ the principal can start a pipeline execution \u2014 the current definition must already run attacker-influenceable\
\ code. Classic ACTIVE cases: a pipeline whose Source stage pulls from a repo branch the attacker\
\ can push to without review (the push both modifies and triggers), or an artifact dependency the\
\ attacker can poison (unpinned package published to an attacker-accessible registry). A fully pinned,\
\ reviewed pipeline definition is CONDITIONAL only. Dedupes with aws-codepipeline-update- pipeline-executes-as\
\ when the principal can BOTH modify and trigger \u2014 the ACTIVE modify edge dominates, do not double-count."
narrative: '{principal.name} can start pipeline {pipeline.name} (codepipeline:StartPipelineExecution),
which executes as {service_role.name}; if the pipeline''s current definition already runs attacker-influenceable
code (poisoned dependency, attacker-authored source, tampered stage spec), this run executes as {service_role.name}.'