aws-ssm-shared-document-cross-account

A shared SSM Automation document gives the sharing-account identity code control over any BuildWorker in the target account that executes it.

derived aws emits CanModifyCode

match

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

{'document': None} CrossAccountTrust {'targetAccount': None} {'owner': None} HasPermission {'document': None} {'targetRunner': None} ExecutesAs {'targetRole': None}

where

node_type(?document) == AutomationService ?document.document_type == 'Automation' effective_action == 'ssm:UpdateDocument' # document owner can modify the definition node_type(?targetRunner) == BuildWorker ?targetRunner.document_arn == ?document.arn # target runner executes this shared document ?targetRunner.account == ?targetAccount.id # runner lives in the target account

emit

source typeIdentity
target typeBuildWorker
source?owner
target?targetRunner
permissionsssm:UpdateDocument
conditionsresource_policy
state logicACTIVE when (a) the document's permission list includes the target account, (b) the sharing-account identity has ssm:UpdateDocument on the document, AND (c) the target account has a runner that executes this document. If the target account's use of the document is not yet confirmed, CONDITIONAL(resource_policy). This edge models the supply-chain risk: the document owner controls the definition the target-account runner executes.

Narrative

The sharing-account principal {owner.name} controls the content of Automation document {document.name} (via ssm:UpdateDocument) shared with account {targetAccount.name}; the target-account runner {targetRunner.name} executes that document as {targetRole.name}, giving {owner.name} indirect code execution in the target account.

Raw rule rules/derived/aws/ssm.yaml

id: aws-ssm-shared-document-cross-account
emits: CanModifyCode
description: A shared SSM Automation document gives the sharing-account identity code control over any
  BuildWorker in the target account that executes it.
match:
- - document: null
  - CrossAccountTrust
  - targetAccount: null
- - owner: null
  - HasPermission
  - document: null
- - targetRunner: null
  - ExecutesAs
  - targetRole: null
where:
- node_type(?document) == AutomationService
- ?document.document_type == 'Automation'
- 'effective_action == ''ssm:UpdateDocument''  # document owner can modify the definition'
- node_type(?targetRunner) == BuildWorker
- '?targetRunner.document_arn == ?document.arn  # target runner executes this shared document'
- '?targetRunner.account == ?targetAccount.id   # runner lives in the target account'
emit:
  source_type: Identity
  target_type: BuildWorker
  source: ?owner
  target: ?targetRunner
  permissions:
  - ssm:UpdateDocument
  conditions:
  - resource_policy
  state_logic: 'ACTIVE when (a) the document''s permission list includes the target account, (b) the sharing-account
    identity has ssm:UpdateDocument on the document, AND (c) the target account has a runner that executes
    this document. If the target account''s use of the document is not yet confirmed, CONDITIONAL(resource_policy).
    This edge models the supply-chain risk: the document owner controls the definition the target-account
    runner executes.'
  confidence: 0.8
  derived_from:
  - ?document CrossAccountTrust ?targetAccount
  - effective ssm:UpdateDocument by ?owner
  - ?targetRunner ExecutesAs ?targetRole
  false_positive_note: Requires confirmation that the target account actually runs the shared document
    (a BuildWorker node with document_arn matching the shared document). Without that confirmation, the
    cross-account trust is a POTENTIAL supply-chain risk, not ACTIVE. The document owner (source = Identity)
    must have ssm:UpdateDocument to modify the definition; merely sharing it does not grant code control
    if the content cannot be changed. ssm:ModifyDocumentPermission is the action that established the
    cross-account sharing trust (present in the CrossAccountTrust edge), but is not required by the document
    owner to modify code after sharing is in place. CanModifyCode.source = [Identity] and .target = [Compute]
    per schema/edges.yaml; AutomationService/Scheduler nodes are ManagementService class and are not in
    scope as target here.
  narrative: The sharing-account principal {owner.name} controls the content of Automation document {document.name}
    (via ssm:UpdateDocument) shared with account {targetAccount.name}; the target-account runner {targetRunner.name}
    executes that document as {targetRole.name}, giving {owner.name} indirect code execution in the target
    account.
move · open · esc close