aws-ssm-update-document-modify-code
ssm:UpdateDocument rewrites a customer-owned Automation document's steps - the executed definition of the BuildWorker runner.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
effective_action == 'ssm:UpdateDocument'
node_type(?document) ==
AutomationService
?document.document_type == 'Automation'
?document.owner != 'Amazon' # AWS-managed documents cannot be updated by customers
node_type(?runner) == BuildWorker
?runner.document_arn == ?document.arn # this runner executes the document being updated
emit
| source type | Identity |
|---|---|
| target type | BuildWorker |
| source | ?principal |
| target | ?runner |
| permissions | ssm:UpdateDocument ssm:UpdateDocumentDefaultVersion |
| conditions | iam_permission |
| state logic | ACTIVE when ssm:UpdateDocument is EFFECTIVE on the document ARN and the document is customer-owned (owner != 'Amazon'). BLOCKED when an SCP / permission boundary denies ssm:UpdateDocument. POTENTIAL when the runner does not yet have an AutomationAssumeRole binding (no execution identity yet). A new version does not automatically become default; ssm:UpdateDocumentDefaultVersion must also be EFFECTIVE for the persistent code modification to become ACTIVE — if ssm:UpdateDocumentDefaultVersion is missing, downgrade to CONDITIONAL(iam_permission) because the new version remains inactive. |
Narrative
{principal.name} can rewrite the steps of Automation document {document.name} (ssm:UpdateDocument), injecting malicious automation steps that will execute as {role.name} via runner {runner.name} on the next invocation.
Raw rule rules/derived/aws/ssm.yaml
id: aws-ssm-update-document-modify-code
emits: CanModifyCode
description: "ssm:UpdateDocument rewrites a customer-owned Automation document's steps \u2014 the executed\
\ definition of the BuildWorker runner."
match:
- - principal: null
- HasPermission
- document: null
- - runner: null
- ExecutesAs
- role: null
where:
- effective_action == 'ssm:UpdateDocument'
- node_type(?document) == AutomationService
- ?document.document_type == 'Automation'
- '?document.owner != ''Amazon'' # AWS-managed documents cannot be updated by customers'
- node_type(?runner) == BuildWorker
- '?runner.document_arn == ?document.arn # this runner executes the document being updated'
emit:
source_type: Identity
target_type: BuildWorker
source: ?principal
target: ?runner
permissions:
- ssm:UpdateDocument
- ssm:UpdateDocumentDefaultVersion
conditions:
- iam_permission
state_logic: "ACTIVE when ssm:UpdateDocument is EFFECTIVE on the document ARN and the document is customer-owned\
\ (owner != 'Amazon'). BLOCKED when an SCP / permission boundary denies ssm:UpdateDocument. POTENTIAL\
\ when the runner does not yet have an AutomationAssumeRole binding (no execution identity yet). A\
\ new version does not automatically become default; ssm:UpdateDocumentDefaultVersion must also be\
\ EFFECTIVE for the persistent code modification to become ACTIVE \u2014 if ssm:UpdateDocumentDefaultVersion\
\ is missing, downgrade to CONDITIONAL(iam_permission) because the new version remains inactive."
confidence: 0.9
derived_from:
- effective ssm:UpdateDocument on ?document
- ?runner ExecutesAs ?role
false_positive_note: "AWS-managed documents (document.owner == 'Amazon', name prefix 'AWS-*') cannot\
\ be modified by customers \u2014 do NOT emit CanModifyCode for them. For those, the code-control\
\ vector is at invocation time via parameter injection (aws-ssm-send-command-execute-command above).\
\ A new document version is inactive until set as default via ssm:UpdateDocumentDefaultVersion or\
\ the default-version promotion flag at UpdateDocument call time \u2014 if that action is not EFFECTIVE,\
\ the persistent-modification impact is CONDITIONAL. The target is the BuildWorker runner node (the\
\ Automation execution), not the document node (AutomationService/ManagementService) \u2014 CanModifyCode.target\
\ must be Compute-class per schema/edges.yaml."
narrative: '{principal.name} can rewrite the steps of Automation document {document.name} (ssm:UpdateDocument),
injecting malicious automation steps that will execute as {role.name} via runner {runner.name} on
the next invocation.'