aws-codepipeline-approval-bypass-unblock-stage
PutApprovalResult APPROVE on a manual approval gate unblocks the downstream stage runner, enabling a principal who can trigger the pipeline AND approve the gate to reach stages that were otherwise CONDITIONAL(stage_reachable).
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
{'principal': None}
CanTrigger {'pipeline': None}
{'pipeline': None} CanTrigger {'stage_runner': None}
where
?pipeline has at least one manual approval action (action type == Approval)
?principal has EFFECTIVE codepipeline:PutApprovalResult on the approval action's ARN
the approval gate is the sole gate blocking ?stage_runner
emit
| source type | Identity |
|---|---|
| target type | Compute |
| source | ?principal |
| target | ?stage_runner |
| permissions | codepipeline:StartPipelineExecution codepipeline:PutApprovalResult |
| conditions | stage_reachable |
| state logic | ACTIVE when the principal can both start the pipeline AND approve the manual gate (PutApprovalResult on the approval action). This UPGRADES a previously CONDITIONAL(stage_reachable) downstream CanTrigger to ACTIVE. If the approval gate uses an SNS topic for external approver notification and the principal cannot call PutApprovalResult, the gate remains a real control — keep CONDITIONAL(stage_reachable). |
Narrative
{principal.name} can start pipeline {pipeline.name} and approve the manual approval gate (codepipeline:PutApprovalResult), bypassing human review and unblocking the downstream stage runner {stage_runner.name} to execute as the action role.
Raw rule rules/derived/aws/codepipeline.yaml
id: aws-codepipeline-approval-bypass-unblock-stage
emits: CanTrigger
description: PutApprovalResult APPROVE on a manual approval gate unblocks the downstream stage runner,
enabling a principal who can trigger the pipeline AND approve the gate to reach stages that were otherwise
CONDITIONAL(stage_reachable).
match:
- - principal: null
- CanTrigger
- pipeline: null
- - pipeline: null
- CanTrigger
- stage_runner: null
where:
- ?pipeline has at least one manual approval action (action type == Approval)
- ?principal has EFFECTIVE codepipeline:PutApprovalResult on the approval action's ARN
- the approval gate is the sole gate blocking ?stage_runner
emit:
source_type: Identity
target_type: Compute
source: ?principal
target: ?stage_runner
permissions:
- codepipeline:StartPipelineExecution
- codepipeline:PutApprovalResult
conditions:
- stage_reachable
state_logic: "ACTIVE when the principal can both start the pipeline AND approve the manual gate (PutApprovalResult\
\ on the approval action). This UPGRADES a previously CONDITIONAL(stage_reachable) downstream CanTrigger\
\ to ACTIVE. If the approval gate uses an SNS topic for external approver notification and the principal\
\ cannot call PutApprovalResult, the gate remains a real control \u2014 keep CONDITIONAL(stage_reachable)."
confidence: min(contributing_confidences) * 0.95
derived_from:
- ?principal CanTrigger ?pipeline
- ?pipeline CanTrigger ?stage_runner
- codepipeline:PutApprovalResult confirms gate bypass
false_positive_note: "Only emit when the principal has EFFECTIVE PutApprovalResult on the specific approval\
\ action ARN in the pipeline stage. The approval action may be restricted by IAM resource conditions\
\ to a specific approver (e.g. a role ARN in the approval action's notificationArn or trigger). If\
\ the principal cannot satisfy the approval's IAM resource condition, the gate is NOT bypassable.\
\ Do not emit ACTIVE for SNS-based approvals where the approver is a human via SNS email notification\
\ \u2014 that is a real out-of-band control."
narrative: '{principal.name} can start pipeline {pipeline.name} and approve the manual approval gate
(codepipeline:PutApprovalResult), bypassing human review and unblocking the downstream stage runner
{stage_runner.name} to execute as the action role.'