aws-amplify-attach-service-role

UpdateApp + iam:PassRole can replace an Amplify App's iamServiceRoleArn, changing the build execution identity.

derived aws emits CanAttachIdentity

match

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

{'principal': None} CanPassIdentity {'role': None}

where

?principal has effective amplify:UpdateApp on the target app ARN ?role trust policy allows amplify.amazonaws.com

emit

source typeIdentity
target typeBuildWorker
source<principal>
target<AWS::Amplify::App>
permissionsamplify:UpdateApp iam:PassRole
conditionsiam_permission role_compatibility
state logicACTIVE if both amplify:UpdateApp on the app ARN and iam:PassRole for a role trusting amplify.amazonaws.com are satisfied. CONDITIONAL(role_compatibility) if the role trust is unresolved. This edge sets up the retarget path: after CanAttachIdentity the app's next build will ExecutesAs the newly attached role, and cicd-chains cicd-modify-buildspec-executes-as fires on (CanModifyCode, new_ExecutesAs) chain. The CanAttachIdentity by itself does not grant execution; it becomes an attack step when combined with a build trigger (amplify:StartJob or auto-build) that fires after the role swap.

Narrative

{principal.name} can replace {app.name}'s IAM service role with {role.name} (amplify:UpdateApp + iam:PassRole), changing the AWS identity the next build executes as.

Raw rule rules/derived/aws/amplify.yaml

id: aws-amplify-attach-service-role
emits: CanAttachIdentity
description: UpdateApp + iam:PassRole can replace an Amplify App's iamServiceRoleArn, changing the build
  execution identity.
match:
- - principal: null
  - CanPassIdentity
  - role: null
where:
- ?principal has effective amplify:UpdateApp on the target app ARN
- ?role trust policy allows amplify.amazonaws.com
emit:
  source_type: Identity
  target_type: BuildWorker
  source: <principal>
  target: <AWS::Amplify::App>
  permissions:
  - amplify:UpdateApp
  - iam:PassRole
  conditions:
  - iam_permission
  - role_compatibility
  state_logic: 'ACTIVE if both amplify:UpdateApp on the app ARN and iam:PassRole for a role trusting amplify.amazonaws.com
    are satisfied. CONDITIONAL(role_compatibility) if the role trust is unresolved. This edge sets up
    the retarget path: after CanAttachIdentity the app''s next build will ExecutesAs the newly attached
    role, and cicd-chains cicd-modify-buildspec-executes-as fires on (CanModifyCode, new_ExecutesAs) chain.
    The CanAttachIdentity by itself does not grant execution; it becomes an attack step when combined
    with a build trigger (amplify:StartJob or auto-build) that fires after the role swap.'
  derived_from:
  - <CanPassIdentity edge_id>
  false_positive_note: UpdateApp is a single API that can simultaneously change buildSpec AND iamServiceRoleArn;
    the attacker can inject build commands AND swap the role in one call. The CanAttachIdentity edge models
    the identity-swap half; CanModifyCode (aws-amplify-modifycode-app) models the buildSpec half. Both
    may fire from a single UpdateApp call. iam:PassRole PassedToService must include amplify.amazonaws.com;
    otherwise Amplify rejects the new role ARN.
  narrative: '{principal.name} can replace {app.name}''s IAM service role with {role.name} (amplify:UpdateApp
    + iam:PassRole), changing the AWS identity the next build executes as.'
move · open · esc close