Cloud Security Wire
AWS Azure GCP RSS
AWS Hardening Guide high

AWS ECR Supply Chain Attacks: Malicious Container Images and How to Stop Them

AWS Elastic Container Registry is a prime target for supply chain attackers. From public gallery namespace poisoning to CI/CD pipeline compromise pushing backdoored images, this guide covers the attack paths and the hardening controls that break them.

By Cloud Security Wire · ·
#ecr#container-registry#supply-chain#aws#docker#kubernetes#image-signing#cosign#ci-cd#malicious-image#iam#lifecycle-policy
High Severity

This issue has been assessed as high severity. Review affected configurations immediately.

Container images are supply chain artifacts. Every image you pull, build on, or run in production carries implicit trust — trust that the base image is what it claims to be, that your CI/CD pipeline hasn’t been poisoned between build and push, and that nobody with ECR write access has swapped out a layer. AWS Elastic Container Registry is where most of that trust is anchored for AWS workloads, and the controls protecting it are frequently under-configured.

This guide covers the realistic attack paths against ECR and the hardening steps that meaningfully reduce exposure.

How Attackers Target ECR

Public ECR Namespace Poisoning

AWS maintains the ECR Public Gallery at public.ecr.aws. Anyone can publish images there without authentication. Threat actors use this to host near-identical images to popular ones — slightly misspelled names (amazonlinux vs amazon-linux), fake “official” versions of popular tools, or images that layer malicious additions on legitimate bases.

Developers who reference public images by name without digest pinning are at risk. When you write FROM public.ecr.aws/some-namespace/some-image:latest, you’re trusting whatever is currently tagged as latest in that namespace. If that image changes, your next build runs the new version.

CI/CD Pipeline Compromise

The most impactful ECR supply chain attacks don’t involve poisoning external images — they involve compromising the pipeline that builds and pushes your images. An attacker who gains access to your CI/CD environment (via a compromised OIDC token, a secret leaked in build logs, or a malicious pull request targeting pull_request_target) can push a backdoored image to your ECR registry under a legitimate tag.

The resulting image passes all your image scanning checks because the backdoor is added post-build. It carries your signing key if you use one, because the signing step runs in the compromised pipeline. This is why defence needs to go deeper than scanning.

Misconfigured ECR Repository Policies

By default, ECR repositories are private. But resource-based policies on repositories can expose them to broader access than intended. Common misconfigurations:

  • Principal: "*" in a resource policy (public access)
  • Overly broad aws:PrincipalOrgPaths conditions allowing pull from any account in the org
  • ecr:GetAuthorizationToken and ecr:BatchGetImage granted to roles that shouldn’t have it
  • Cross-account write access granted to CI/CD roles in sub-accounts without IP condition restrictions

Tag Mutation Attacks

Docker image tags are mutable. If an attacker gains ecr:PutImage permissions, they can push a different image under an existing tag. Your v1.2.3 image can be silently replaced. Unless you’re referencing images by immutable digest (sha256:...), you won’t know.

Hardening Steps

1. Enable Immutable Image Tags

Prevent tag mutation at the registry level:

aws ecr put-image-tag-mutability \
  --repository-name your-repo \
  --image-tag-mutability IMMUTABLE

With immutable tags, any attempt to push a new image under an existing tag fails. This eliminates tag mutation attacks as a vector and forces version increments for all changes — which also improves auditability.

2. Enable ECR Image Scanning

Turn on enhanced scanning (powered by Amazon Inspector) at the registry level:

aws ecr put-registry-scanning-configuration \
  --scan-type ENHANCED \
  --rules '[{
    "repositoryFilters": [{"filter": "*", "filterType": "WILDCARD"}],
    "scanFrequency": "CONTINUOUS_SCAN"
  }]'

Enhanced scanning evaluates OS packages, programming language packages, and provides EPSS scores. Integrate scan results into your CI/CD pipeline to block pushes of images with critical vulnerabilities:

# Check scan findings before allowing deploy
FINDINGS=$(aws ecr describe-image-scan-findings \
  --repository-name your-repo \
  --image-id imageDigest=sha256:... \
  --query 'imageScanFindings.findingSeverityCounts.CRITICAL' \
  --output text)

if [ "$FINDINGS" -gt 0 ]; then
  echo "Critical vulnerabilities found. Blocking deployment."
  exit 1
fi

3. Sign Images with AWS Signer or Cosign

Image signing lets you verify that an image was built by your trusted pipeline and hasn’t been tampered with:

# Install cosign
cosign sign \
  --key awskms:///arn:aws:kms:us-east-1:123456789012:key/your-key-id \
  123456789012.dkr.ecr.us-east-1.amazonaws.com/your-repo:v1.2.3

# Verify at deploy time
cosign verify \
  --key awskms:///arn:aws:kms:us-east-1:123456789012:key/your-key-id \
  123456789012.dkr.ecr.us-east-1.amazonaws.com/your-repo:v1.2.3

Enforce signature verification in Kubernetes using Kyverno or OPA/Gatekeeper policies that reject unsigned or unverified images at admission.

4. Lock Down ECR IAM Permissions

Apply least-privilege IAM to ECR. CI/CD pipelines should have push-only permissions scoped to specific repositories:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecr:GetAuthorizationToken"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:PutImage",
        "ecr:InitiateLayerUpload",
        "ecr:UploadLayerPart",
        "ecr:CompleteLayerUpload"
      ],
      "Resource": "arn:aws:ecr:us-east-1:123456789012:repository/your-repo"
    }
  ]
}

Separate read and write roles. Deployment infrastructure should have pull-only access. Add a condition to restrict ecr:PutImage to calls from your CI/CD OIDC provider’s IP ranges or OIDC subject conditions.

5. Pin Images to Digest in Production

Reference production images by digest, not tag:

# In Kubernetes manifests:
image: 123456789012.dkr.ecr.us-east-1.amazonaws.com/your-repo@sha256:a1b2c3d4...

A digest is immutable and content-addressed. If the image changes, the digest changes, and the reference breaks. This forces an explicit update when you want to change what’s running.

6. Audit ECR Pull Activity with CloudTrail

Monitor for anomalous pull activity:

# Find ECR pulls from outside your account
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=GetDownloadUrlForLayer \
  --start-time 2026-07-17T00:00:00Z \
  --end-time 2026-07-24T00:00:00Z \
  --query 'Events[?userIdentity.accountId!=`123456789012`]'

Alert on BatchGetImage or GetDownloadUrlForLayer events from unexpected source accounts, IAM roles, or geographic regions. An attacker who exfiltrates your private image to analyse it or extract embedded secrets will generate these events.

Putting It Together

Effective ECR supply chain defence layers these controls: immutable tags prevent silent replacement, image signing verifies build provenance, scanning catches known vulnerabilities, and CloudTrail monitoring detects unauthorised access. None of these controls alone is sufficient — a compromised pipeline bypasses scanning and signs with your key. Defence-in-depth across the build, push, and pull phases is what makes the supply chain actually trustworthy.

← All Analysis Subscribe via RSS