aws-ecr-pull-can-read-data

A principal with effective ecr:BatchGetImage + ecr:GetDownloadUrlForLayer can pull image layers, reading embedded secrets or proprietary code contained in the repository's images. For KMS-encrypted repositories, the principal must also hold kms:Decrypt on the repository's CMK.

derived aws emits CanReadData

match

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

{'principal': None} HasPermission {'repository': None}

where

node_type(?repository) == ContainerRegistry ?repository.provider_type in ['AWS::ECR::Repository', 'AWS::ECR::PublicRepository'] effective_permission(?principal, 'ecr:BatchGetImage', ?repository) == true effective_permission(?principal, 'ecr:GetDownloadUrlForLayer', ?repository) == true effective_permission(?principal, 'ecr:GetAuthorizationToken', '*') == true ?repository.encryptionConfiguration.encryptionType != 'KMS' OR effective_permission(?principal, 'kms:Decrypt', ?repository.kmsKey) == true

emit

source typeIdentity
target typeContainerRegistry
source?principal
target?repository
permissionsecr:GetAuthorizationToken ecr:BatchGetImage ecr:GetDownloadUrlForLayer
conditionsiam_permission resource_policy key_permission
state logicACTIVE when the principal has effective pull permissions (BatchGetImage + GetDownloadUrlForLayer + GetAuthorizationToken) as confirmed by effective permission evaluation, not blocked by SCP or permission boundary, AND either the repository is NOT KMS-encrypted OR the principal holds kms:Decrypt on the configured CMK. CONDITIONAL(resource_policy) when pull access is granted only by the resource policy (not the identity policy). CONDITIONAL(key_permission) when the repository is KMS-encrypted and the principal lacks kms:Decrypt on the CMK — the pull will fail at runtime without the key permission. The security value of this edge depends on whether the images actually contain sensitive data (ContainsSecret / ContainsCredential facts drive CanReadSecret derivation in credential-chains).

Narrative

{principal.name} can pull images from {repository.name} (ecr:BatchGetImage + ecr:GetDownloadUrlForLayer + ecr:GetAuthorizationToken) and inspect layer contents, potentially reading embedded secrets, credentials, or proprietary code baked into the image layers. {if KMS-encrypted: Decryption requires kms:Decrypt on the repository's CMK ({repository.kmsKey}); the edge is CONDITIONAL without it.}

Raw rule rules/derived/aws/ecr.yaml

id: aws-ecr-pull-can-read-data
emits: CanReadData
description: A principal with effective ecr:BatchGetImage + ecr:GetDownloadUrlForLayer can pull image
  layers, reading embedded secrets or proprietary code contained in the repository's images. For KMS-encrypted
  repositories, the principal must also hold kms:Decrypt on the repository's CMK.
match:
- - principal: null
  - HasPermission
  - repository: null
where:
- node_type(?repository) == ContainerRegistry
- ?repository.provider_type in ['AWS::ECR::Repository', 'AWS::ECR::PublicRepository']
- effective_permission(?principal, 'ecr:BatchGetImage', ?repository) == true
- effective_permission(?principal, 'ecr:GetDownloadUrlForLayer', ?repository) == true
- effective_permission(?principal, 'ecr:GetAuthorizationToken', '*') == true
- ?repository.encryptionConfiguration.encryptionType != 'KMS' OR effective_permission(?principal, 'kms:Decrypt',
  ?repository.kmsKey) == true
emit:
  source_type: Identity
  target_type: ContainerRegistry
  source: ?principal
  target: ?repository
  permissions:
  - ecr:GetAuthorizationToken
  - ecr:BatchGetImage
  - ecr:GetDownloadUrlForLayer
  conditions:
  - iam_permission
  - resource_policy
  - key_permission
  state_logic: "ACTIVE when the principal has effective pull permissions (BatchGetImage + GetDownloadUrlForLayer\
    \ + GetAuthorizationToken) as confirmed by effective permission evaluation, not blocked by SCP or\
    \ permission boundary, AND either the repository is NOT KMS-encrypted OR the principal holds kms:Decrypt\
    \ on the configured CMK. CONDITIONAL(resource_policy) when pull access is granted only by the resource\
    \ policy (not the identity policy). CONDITIONAL(key_permission) when the repository is KMS-encrypted\
    \ and the principal lacks kms:Decrypt on the CMK \u2014 the pull will fail at runtime without the\
    \ key permission. The security value of this edge depends on whether the images actually contain sensitive\
    \ data (ContainsSecret / ContainsCredential facts drive CanReadSecret derivation in credential-chains)."
  confidence: 0.8
  derived_from:
  - effective_permission(?principal, ecr:BatchGetImage, ?repository)
  - effective_permission(?principal, ecr:GetDownloadUrlForLayer, ?repository)
  - effective_permission(?principal, ecr:GetAuthorizationToken, *)
  false_positive_note: "Pull access is common and often legitimate (e.g. the ECS task execution role needs\
    \ it). This edge's escalation value is realized only when the repository images actually contain secrets\
    \ (ContainsSecret) or proprietary code. Do not flag all pull grants as high-severity; gate on ContainsSecret\
    \ / ContainsCredential confirmation before routing this edge to analyst review. Cross-account pull\
    \ (via repository policy) is standard \u2014 model the policy as CrossAccountTrust but do not treat\
    \ pull-only cross-account grants as push. For KMS-encrypted repositories, the edge is CONDITIONAL(key_permission)\
    \ until the principal is confirmed to hold kms:Decrypt on the CMK; do not claim ACTIVE read capability\
    \ without the key permission."
  narrative: '{principal.name} can pull images from {repository.name} (ecr:BatchGetImage + ecr:GetDownloadUrlForLayer
    + ecr:GetAuthorizationToken) and inspect layer contents, potentially reading embedded secrets, credentials,
    or proprietary code baked into the image layers. {if KMS-encrypted: Decryption requires kms:Decrypt
    on the repository''s CMK ({repository.kmsKey}); the edge is CONDITIONAL without it.}'
move · open · esc close