aws-ecr-registry-replication-cross-account-trust

A registry-level replication policy allows an external account's repository to replicate images into the victim's registry, enabling cross-account supply-chain poisoning via the replication mechanism.

derived aws emits CrossAccountTrust

match

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

{'repository': None} HasPolicy {'registry_policy': None}

where

node_type(?repository) == ContainerRegistry ?repository.provider_type in ['AWS::ECR::Repository'] ?registry_policy is the account-level registry policy of ?repository.account (via ecr:GetRegistryPolicy) ?registry_policy grants ecr:ReplicateImage (or implied by ecr:*) to a principal in a different account

emit

source typeResourcePolicy
target typeExternalIdentity
source?registry_policy
target<external account named in the registry's replication policy>
permissionsecr:PutRegistryPolicy ecr:PutReplicationConfiguration
conditionsresource_policy
state logicACTIVE when the registry-level policy grants cross-account replication to an external account and the policy is not overridden by an SCP or deny policy. CONDITIONAL(resource_policy) when the policy includes a Condition gate (e.g. aws:PrincipalOrgID) — the cross-account replication is then conditional on those conditions holding. BLOCKED when an SCP or deny assignment blocks cross-account replication.

Narrative

{registry_policy.name} (the account-level registry policy of account {repository.account}) grants cross-account replication to {external.name} in account {external.account}. If the external account's repository is attacker-controlled, they can replicate poisoned images into {repository.account}'s registry, where downstream workloads will pull and execute them.

Raw rule rules/derived/aws/ecr.yaml

id: aws-ecr-registry-replication-cross-account-trust
emits: CrossAccountTrust
description: A registry-level replication policy allows an external account's repository to replicate
  images into the victim's registry, enabling cross-account supply-chain poisoning via the replication
  mechanism.
match:
- - repository: null
  - HasPolicy
  - registry_policy: null
where:
- node_type(?repository) == ContainerRegistry
- ?repository.provider_type in ['AWS::ECR::Repository']
- ?registry_policy is the account-level registry policy of ?repository.account (via ecr:GetRegistryPolicy)
- ?registry_policy grants ecr:ReplicateImage (or implied by ecr:*) to a principal in a different account
emit:
  source_type: ResourcePolicy
  target_type: ExternalIdentity
  source: ?registry_policy
  target: <external account named in the registry's replication policy>
  permissions:
  - ecr:PutRegistryPolicy
  - ecr:PutReplicationConfiguration
  conditions:
  - resource_policy
  state_logic: "ACTIVE when the registry-level policy grants cross-account replication to an external\
    \ account and the policy is not overridden by an SCP or deny policy. CONDITIONAL(resource_policy)\
    \ when the policy includes a Condition gate (e.g. aws:PrincipalOrgID) \u2014 the cross-account replication\
    \ is then conditional on those conditions holding. BLOCKED when an SCP or deny assignment blocks cross-account\
    \ replication."
  confidence: 0.88
  derived_from:
  - ?repository HasPolicy ?registry_policy (account-level registry policy grants cross-account replication)
  false_positive_note: "Replication must cross account boundaries to constitute a CrossAccountTrust \u2014\
    \ same-account replication does not emit this edge. Validate that the principal named in the policy\
    \ is in a different account from the repository's account. Honor Condition gates: if the policy restricts\
    \ replication to members of an org via aws:PrincipalOrgID, mark as CONDITIONAL(condition_expression)."
  narrative: '{registry_policy.name} (the account-level registry policy of account {repository.account})
    grants cross-account replication to {external.name} in account {external.account}. If the external
    account''s repository is attacker-controlled, they can replicate poisoned images into {repository.account}''s
    registry, where downstream workloads will pull and execute them.'
move · open · esc close