aws-amplify-modifycode-app
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 — 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.'