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.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
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 — 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.}'