Container Registry Security: Hardening ECR, ACR, and GCR for Production Workloads

Retool's new app builder is where AI-generated code ships safely
Building apps with AI is easy. Getting them to production safely is another story.
Container registries are the distribution point for every containerized workload your organization runs. An image that is pushed with a malicious layer, pulled from an unscanned source, or authenticated via a leaked static credential represents a supply chain risk that bypasses application security controls entirely -- the malicious code runs inside what looks like a legitimate container. The controls that matter are: restricting who can push and pull, enforcing image scanning before deployment, preventing tag mutation, signing images to guarantee provenance, and eliminating static credentials from CI/CD pipeline registry authentication. This guide covers each control for AWS ECR, Azure ACR, and GCP Artifact Registry.
AWS ECR: Scanning, Immutable Tags, and Access Policy
ECR is the AWS-native container registry with native integration into Inspector v2 for vulnerability scanning. Security hardening focuses on preventing public repository exposure, enabling continuous scanning, locking down cross-account access, and enforcing tag immutability.
Enable Inspector v2 for enhanced image scanning
ECR basic scanning uses an open-source scanner for OS packages only. Inspector v2 provides enhanced scanning with programming language package CVE detection, continuous re-scanning as new CVEs are published, and integration with ECR to surface findings in the ECR console. Enable Inspector v2 in each region and configure ECR to use enhanced scanning under Registry settings.
Enforce immutable image tags
Enable image tag immutability on all ECR repositories via the console or CLI: aws ecr put-image-tag-mutability --repository-name my-app --image-tag-mutability IMMUTABLE. This prevents any push from overwriting an existing tag, eliminating the attack vector where a legitimate tag is replaced with a malicious image.
Block public access and apply repository policies
Ensure no ECR repositories are configured as public unless explicitly required. For cross-account pull access, apply a repository resource policy granting only the specific IAM role in the target account the ecr:GetDownloadUrlForLayer, ecr:BatchGetImage, and ecr:BatchCheckLayerAvailability actions. Do not use wildcard principals in repository policies.
Enforce lifecycle policies to remove unscanned images
ECR lifecycle policies can automatically expire images older than a threshold or images that have not been tagged. Create a policy that removes untagged images after 7 days and images failing Inspector findings above HIGH severity. This prevents the registry from accumulating vulnerable old images that might be pulled if a version pin is loosened.
Azure ACR: Private Endpoints, Managed Identity, and Notation Signing
Azure Container Registry supports geo-replication, private endpoint connectivity, managed identity-based pull access, and image signing via Notation with Azure Key Vault. The most important controls are eliminating admin user access, using private endpoints instead of public registry access, and signing images with AKV-backed certificates.
Disable the admin user
ACR has a built-in admin user account that provides username/password credentials for registry access. Disable it immediately: az acr update --name myregistry --admin-enabled false. All access should be via Entra ID identities with the AcrPull or AcrPush role assigned, not via static admin credentials.
Configure private endpoints for registry access
Deploy an Azure Private Endpoint for the registry and disable public network access (az acr update --name myregistry --public-network-enabled false). Registry operations from AKS clusters and pipeline agents route through the private endpoint over the VNet rather than the public internet, eliminating exposure to internet-based attacks.
Use managed identity for AKS pull access
Attach the AKS cluster's managed identity to the registry with the AcrPull role: az role assignment create --assignee <kubelet-identity-client-id> --role AcrPull --scope /subscriptions/.../registries/myregistry. This eliminates the imagePullSecrets pattern that requires storing registry credentials in Kubernetes secrets.
Sign images with Notation and Azure Key Vault
Use the notation CLI with the AKV plugin to sign images using certificates stored in Azure Key Vault. The signing key never leaves AKV. Verification is enforced via Ratify running as an admission controller in AKS, which validates the Notation signature on every pod admission. Unsigned images are blocked from running.
Configure webhook notifications for push events
ACR webhooks can notify a security monitoring endpoint on every image push. Configure a webhook pointing to a Lambda function or Azure Function that calls the registry API to check for new Inspector or Security Center findings and alerts the security team if a newly pushed image has critical vulnerabilities.
Briefings like this, every morning before 9am.
Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.
GCP Artifact Registry: IAM, VPC-SC, and Binary Authorization
GCP replaced Google Container Registry (gcr.io) with Artifact Registry as the recommended container registry. Artifact Registry uses GCP IAM for access control and integrates with Container Analysis for vulnerability scanning and Binary Authorization for deployment enforcement.
Apply least-privilege IAM roles
Use roles/artifactregistry.reader for pull-only access and roles/artifactregistry.writer for push access. Avoid roles/artifactregistry.admin except for the pipeline service account that manages the registry itself. Grant roles at the repository level, not the project level, to scope access to specific registries.
Include the registry in a VPC Service Controls perimeter
Add Artifact Registry to a VPC-SC perimeter to prevent exfiltration of images by compromised service account credentials from outside the defined network boundary. Pipeline agents running outside GCP need to be added to the perimeter's access policy via their external IP range or OIDC identity.
Enable Container Analysis scanning and vulnerability notifications
Enable Container Analysis in the GCP project. Container Analysis automatically scans images pushed to Artifact Registry and re-scans them as new CVEs are published. Configure Pub/Sub notifications on the Container Analysis note so that new HIGH or CRITICAL findings trigger an alert to your security team.
Configure Binary Authorization policy
Create a Binary Authorization policy requiring attestations from your Container Analysis vulnerability scan and your CI build signer before any image can be deployed to GKE or Cloud Run. Set the default rule to 'DENY_ALL' and add per-image allow rules or attestation requirements. This enforces that only scanned, signed images from your CI pipeline run in production.
Image Signing with cosign and Digest Pinning
Image signing and digest pinning are the two controls that guarantee the image you built is the image that runs in production. They operate at different layers -- signing proves provenance, digest pinning prevents accidental or malicious tag drift -- and both should be applied.
Sign images in CI using cosign with keyless signing
In GitHub Actions, cosign's keyless signing uses the runner's OIDC identity to obtain a Sigstore Fulcio certificate and sign the image. The signature and certificate are stored in the registry alongside the image and logged in the Rekor transparency log. No long-lived signing key is stored in CI secrets. Run: cosign sign --yes myregistry/myapp@sha256:<digest> as a post-build step.
Verify signatures in the pull pipeline before deployment
Before deploying an image, verify its cosign signature: cosign verify --certificate-identity=https://github.com/myorg/myrepo/.github/workflows/build.yml@refs/heads/main --certificate-oidc-issuer=https://token.actions.githubusercontent.com myregistry/myapp@sha256:<digest>. Integrate this verification step into your deployment pipeline and fail the deployment if verification does not succeed.
Pin all image references to digests
In Kubernetes manifests, Helm values, and pipeline pull steps, reference images by digest: image: myregistry/myapp@sha256:abc123... rather than by tag. Digest references are immutable -- the same digest always resolves to the same image bytes. Use a tool like crane digest or docker buildx imagetools inspect to retrieve the digest after a build and inject it into deployment manifests.
OIDC-Based Registry Authentication in CI/CD Pipelines
Static registry credentials stored in pipeline secrets are a persistent source of credential exposure. All three cloud providers support OIDC-based authentication from CI/CD platforms that eliminates the need to store any registry password.
GitHub Actions to ECR via AWS OIDC
Configure an IAM OIDC identity provider for GitHub Actions and create an IAM role with ECR pull/push permissions and a trust policy restricted to the specific repository and branch. In the workflow, use aws-actions/configure-aws-credentials@v4 with role-to-assume, then call aws ecr get-login-password to obtain a short-lived registry token. No AWS credentials are stored in GitHub secrets.
GitHub Actions to ACR via federated identity
Create an Entra ID app registration with a federated identity credential pointing to the GitHub Actions OIDC issuer and specific repository. Assign AcrPush on the registry to the app registration. In the workflow, use azure/login@v2 with client-id and tenant-id (no client-secret), then az acr login to obtain a registry token. Credentials are exchanged at runtime via OIDC.
GitHub Actions to Artifact Registry via Workload Identity Federation
Configure a GCP Workload Identity Pool and Provider for GitHub Actions. Create a service account with Artifact Registry writer permissions and bind the GitHub Actions identity to it. In the workflow, use google-github-actions/auth@v2 with workload_identity_provider and service_account, then docker login to the Artifact Registry endpoint. No GCP service account key is stored in GitHub.
The bottom line
Container registry security requires controls at every layer of the image lifecycle: scan on push and continuously for new CVEs, enforce immutable tags to prevent tag overwrite attacks, use private endpoints or VPC-SC to prevent public registry exposure, sign images in CI using cosign or Notation so signatures can be verified at deploy time, pin all production image references to digests, and eliminate static registry credentials from CI/CD pipelines by migrating to OIDC-based authentication on all three cloud platforms. Binary Authorization on GKE enforces that only attested images run in production and is the strongest deploy-time control available.
Frequently asked questions
What is the difference between image tag and image digest, and why does it matter for security?
An image tag like 'myapp:latest' is a mutable pointer that can be reassigned to a different image at any time. A digest like 'myapp@sha256:abc123...' is an immutable cryptographic hash of the image manifest -- it will always refer to exactly the same image content. Pinning Kubernetes manifests and pipeline pull steps to digest references prevents tag-based supply chain attacks where a legitimate tag is overwritten with a malicious image.
How does immutable tag enforcement work in ECR?
Enabling image tag immutability on an ECR repository prevents any push from overwriting an existing tag. Once 'myapp:1.2.3' is pushed, that tag cannot be reassigned to a different image digest. Attempts to push with the same tag return an error. This eliminates the attack vector where an attacker with push access overwrites a legitimate release tag with a malicious image.
What is the difference between cosign and notation for image signing?
Cosign (part of the Sigstore project) signs OCI images using either keyless signing tied to an OIDC identity (a GitHub Actions runner identity, for example) or traditional key-based signing. Notation (CNCF project, used by Azure's AKV signing integration) uses X.509 certificates stored in a key management service and produces OCI reference-type signatures. Both produce signatures stored in the same registry alongside the image. The choice typically follows the cloud provider: cosign integrates naturally with Sigstore's keyless model in GitHub Actions; notation integrates with Azure Key Vault for ACR signing.
What is Binary Authorization and how does it relate to GCR?
Binary Authorization is a GCP policy enforcement service that requires container images deployed to GKE, Cloud Run, or GCE to have attestations from specified authorities before deployment is allowed. Attestations are cryptographic signatures indicating an image passed a specific check -- a Vulnerability Scanning attestation from Container Analysis, a QA sign-off, or a security team sign-off. Binary Authorization enforces these attestations at deploy time, preventing images without required attestations from running even if they are present in the registry.
How should CI/CD pipelines authenticate to container registries without static credentials?
All three cloud providers support OIDC-based authentication for CI/CD pipelines. GitHub Actions can assume an AWS IAM role via OIDC, authenticate to an Azure service principal via federated identity, or impersonate a GCP service account via Workload Identity Federation. The pipeline receives a short-lived token rather than a stored secret. For ECR this means the pipeline calls 'aws ecr get-login-password' using temporary STS credentials from the assumed role. No registry password is stored in the pipeline configuration.
What is an ECR repository policy and how does it differ from IAM policy?
An ECR repository policy is a resource-based policy attached directly to the repository that controls access to that specific repository. IAM policies attached to users, roles, or groups are identity-based and can also grant ECR access. Both must allow an action for cross-account access to work. Repository policies are the primary mechanism for granting cross-account access -- you attach a repository policy that allows a role from another account to pull from the repository, without needing IAM changes in the target account.
How does VPC Service Controls protect GCP Artifact Registry?
VPC Service Controls (VPC-SC) creates a security perimeter around GCP services including Artifact Registry. When a registry is inside a perimeter, API calls to it from outside the perimeter (from the internet or from GCP projects not in the perimeter) are blocked regardless of IAM permissions. This prevents data exfiltration: even if an attacker obtains valid service account credentials, they cannot pull images from outside the defined perimeter. Access from CI/CD pipelines outside GCP requires the pipeline's source IP or identity to be in the perimeter's access policy.
Sources & references
Free resources
Critical CVE Reference Card 2025–2026
25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.
Ransomware Incident Response Playbook
Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.
Get threat intel before your inbox does.
50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.
Unsubscribe anytime. We never sell your data.

Founder & Cybersecurity Evangelist, Decryption Digest
Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.
Win a $2,495 Black Hat pass.
Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.
