aws-amplify-modifycode-app

amplify:UpdateApp with buildSpec field rewrites the app-level build commands for all branches.

derived aws emits CanModifyCode

match (effective permission)

{ "action": "amplify:UpdateApp", "resource_type": "AWS::Amplify::App" }

emit

source typeIdentity
target typeBuildWorker
source<principal>
target<AWS::Amplify::App in scope>
permissionsamplify:UpdateApp
conditionsiam_permission
state logicACTIVE if iam_permission is satisfied. A branch-level buildSpec override on an individual branch takes precedence over the app-level buildSpec for that branch (see aws-amplify-modifycode-branch); the app-level injection still poisons all other branches. If the source repo contains an amplify.yml, that file overrides the console-stored buildSpec for each build — the app-level injection has no effect on those branches until the amplify.yml is removed. Emit CONDITIONAL(service_state) if the app has no connected branch with a run path.

Narrative

{principal.name} can rewrite the app-level build commands of {app.name} (amplify:UpdateApp buildSpec field), injecting arbitrary shell commands that will run as the app's service role on the next build of any branch that does not have its own branch-level buildSpec override.

Raw rule rules/derived/aws/amplify.yaml

id: aws-amplify-modifycode-app
emits: CanModifyCode
description: amplify:UpdateApp with buildSpec field rewrites the app-level build commands for all branches.
match_effective_permission:
  action: amplify:UpdateApp
  resource_type: AWS::Amplify::App
emit:
  source_type: Identity
  target_type: BuildWorker
  source: <principal>
  target: <AWS::Amplify::App in scope>
  permissions:
  - amplify:UpdateApp
  conditions:
  - iam_permission
  state_logic: "ACTIVE if iam_permission is satisfied. A branch-level buildSpec override on an individual\
    \ branch takes precedence over the app-level buildSpec for that branch (see aws-amplify-modifycode-branch);\
    \ the app-level injection still poisons all other branches. If the source repo contains an amplify.yml,\
    \ that file overrides the console-stored buildSpec for each build \u2014 the app-level injection has\
    \ no effect on those branches until the amplify.yml is removed. Emit CONDITIONAL(service_state) if\
    \ the app has no connected branch with a run path."
  confidence: 0.95
  derived_from:
  - '<HasPermission edge: ?principal amplify:UpdateApp on ?app>'
  false_positive_note: "UpdateApp is the single Amplify action that touches both buildSpec AND iamServiceRoleArn\
    \ AND environmentVariables. This CanModifyCode rule is scoped to the buildSpec field; aws-amplify-modifyconfig-app\
    \ handles the identity/config mutation. If the permission is scoped by a resource tag condition, honor\
    \ it. If the app has no iamServiceRoleArn (no ExecutesAs edge), CanModifyCode is still emitted (the\
    \ fact exists) but cicd-chains cicd-modify-buildspec-executes-as will NOT fire (no ExecutesAs partner)\
    \ \u2014 the path dead-ends correctly. If the source repo contains an amplify.yml that overrides the\
    \ stored buildSpec, downgrade to POTENTIAL(amplify.yml_overrides_stored_buildspec)."
  narrative: '{principal.name} can rewrite the app-level build commands of {app.name} (amplify:UpdateApp
    buildSpec field), injecting arbitrary shell commands that will run as the app''s service role on the
    next build of any branch that does not have its own branch-level buildSpec override.'
move · open · esc close