aws-codedeploy-trigger-executes-as-service-role

Trigger a deployment to execute orchestration-plane actions as the deployment group's service role - requires a run path.

derived aws emits CanExecuteAs

match

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

{'principal': None} CanModifyCode {'deploygroup': None} {'deploygroup': None} ExecutesAs {'servicerole': None}

where

node_type(?deploygroup) == AutomationService ?deploygroup.provider_type == AWS::CodeDeploy::DeploymentGroup ?servicerole.provider_type == AWS::IAM::Role ?servicerole.privilege_level > ?principal.privilege_level

optional

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

{'principal': None} CanTrigger {'deploygroup': None}

emit

source typeIdentity
target typeRole
source?principal
target?servicerole
permissionscodedeploy:CreateDeployment
conditionsiam_permission service_state trigger_exists
state logicACTIVE when ?principal has effective codedeploy:CreateDeployment on ?deploygroup AND ?deploygroup is ACTIVE (not paused/stopped) AND ?servicerole is more privileged than ?principal AND a deployment trigger exists (matched(optional[0]) or an armed trigger like CodePipeline / webhook / schedule). CONDITIONAL (trigger_exists) when the principal can modify the group but cannot trigger a deployment — the service role is only exercised when a deployment runs, and without a trigger mechanism, the modification does not yield execution. Only emit when privilege(?servicerole) > privilege(?principal) — the service role credentials are exercised by the CodeDeploy service process, not directly by attacker code running on instances. Strictly weaker than the instance-role RCE path because it is orchestration-plane, not arbitrary-code execution. Inherits weakest of CanModifyCode and ExecutesAs contributors.

Narrative

{principal.name} can trigger a CodeDeploy deployment (codedeploy:CreateDeployment) that exercises the service role {servicerole.name}; this lets the principal indirectly leverage {servicerole.name}'s orchestration-plane permissions (ELB deregister, ASG, EC2 tag/describe) through the CodeDeploy control plane.

Raw rule rules/derived/aws/codedeploy.yaml

id: aws-codedeploy-trigger-executes-as-service-role
emits: CanExecuteAs
description: "Trigger a deployment to execute orchestration-plane actions as the deployment group's service\
  \ role \u2014 requires a run path."
match:
- - principal: null
  - CanModifyCode
  - deploygroup: null
- - deploygroup: null
  - ExecutesAs
  - servicerole: null
where:
- node_type(?deploygroup) == AutomationService
- ?deploygroup.provider_type == AWS::CodeDeploy::DeploymentGroup
- ?servicerole.provider_type == AWS::IAM::Role
- ?servicerole.privilege_level > ?principal.privilege_level
optional:
- - principal: null
  - CanTrigger
  - deploygroup: null
emit:
  source_type: Identity
  target_type: Role
  source: ?principal
  target: ?servicerole
  permissions:
  - codedeploy:CreateDeployment
  conditions:
  - iam_permission
  - service_state
  - trigger_exists
  state_logic: "ACTIVE when ?principal has effective codedeploy:CreateDeployment on ?deploygroup AND ?deploygroup\
    \ is ACTIVE (not paused/stopped) AND ?servicerole is more privileged than ?principal AND a deployment\
    \ trigger exists (matched(optional[0]) or an armed trigger like CodePipeline / webhook / schedule).\
    \ CONDITIONAL (trigger_exists) when the principal can modify the group but cannot trigger a deployment\
    \ \u2014 the service role is only exercised when a deployment runs, and without a trigger mechanism,\
    \ the modification does not yield execution. Only emit when privilege(?servicerole) > privilege(?principal)\
    \ \u2014 the service role credentials are exercised by the CodeDeploy service process, not directly\
    \ by attacker code running on instances. Strictly weaker than the instance-role RCE path because it\
    \ is orchestration-plane, not arbitrary-code execution. Inherits weakest of CanModifyCode and ExecutesAs\
    \ contributors."
  confidence: 0.75
  derived_from:
  - ?principal CanModifyCode ?deploygroup
  - ?deploygroup ExecutesAs ?servicerole
  false_positive_note: "The CodeDeploy service role is exercised by the CodeDeploy service plane, not\
    \ by attacker code running on instances. The attacker cannot call AWS APIs as the service role directly;\
    \ they can only observe its side effects (ELB deregister/ register, ASG lifecycle hooks, EC2 tag).\
    \ Emit at confidence 0.75 to reflect this indirect control. If the service role has only narrow permissions\
    \ (ELB deregister/register, EC2 describe), it may not be a meaningful escalation \u2014 only emit\
    \ when privilege(?servicerole) > privilege(?principal). A deployment trigger (manual creation via\
    \ codedeploy:CreateDeployment, or an armed trigger from CodePipeline / webhook / schedule) must exist\
    \ for the service role to be exercised. Without a trigger, downgrade to CONDITIONAL(trigger_exists).\
    \ Cite can-execute-as for the escalation roll-up; do not re-derive CanEscalateTo here."
  narrative: '{principal.name} can trigger a CodeDeploy deployment (codedeploy:CreateDeployment) that
    exercises the service role {servicerole.name}; this lets the principal indirectly leverage {servicerole.name}''s
    orchestration-plane permissions (ELB deregister, ASG, EC2 tag/describe) through the CodeDeploy control
    plane.'
move · open · esc close