This issue has been assessed as high severity. Review affected configurations immediately.
GCP Artifact Registry replaced Container Registry as Google’s recommended container and artifact storage service, and it has inherited — and in some cases amplified — the IAM misconfiguration patterns that have plagued cloud storage security for years. As Artifact Registry becomes the central distribution point for container images in GCP environments, misconfigurations here affect every workload that pulls from it.
Three categories account for the majority of Artifact Registry-related security incidents: publicly accessible repositories, overpermissive service account bindings, and secrets embedded in container image layers.
Misconfiguration 1: Public Repository Access
Artifact Registry supports IAM conditions that, when misconfigured, expose repositories to the public internet. The two dangerous bindings are allUsers (unauthenticated access) and allAuthenticatedUsers (any Google account, authenticated or not — effectively public for practical purposes).
These bindings most commonly appear when:
- A developer manually enables public access to share an image without understanding the IAM model
- A Terraform module sets overly broad conditions and the configuration is copy-pasted into production
- Registry permissions are bulk-updated during a migration from Container Registry
Audit your repositories:
# List all repositories in a project
gcloud artifacts repositories list --project=YOUR_PROJECT_ID
# Check IAM policy for a specific repository
gcloud artifacts repositories get-iam-policy REPO_NAME \
--location=us-central1 \
--project=YOUR_PROJECT_ID
Look for any binding containing allUsers or allAuthenticatedUsers. Either is a misconfiguration unless the image is genuinely a public distribution (open-source base images, for example).
Check all repos at once with a shell loop:
for repo in $(gcloud artifacts repositories list --project=YOUR_PROJECT \
--format="value(name)"); do
policy=$(gcloud artifacts repositories get-iam-policy $repo \
--project=YOUR_PROJECT 2>/dev/null)
if echo "$policy" | grep -q "allUsers\|allAuthenticatedUsers"; then
echo "PUBLIC ACCESS DETECTED: $repo"
fi
done
Remediation: Remove overpermissive bindings and restrict access to specific service accounts or groups:
gcloud artifacts repositories remove-iam-policy-binding REPO_NAME \
--location=us-central1 \
--member="allUsers" \
--role="roles/artifactregistry.reader" \
--project=YOUR_PROJECT_ID
Misconfiguration 2: Overpermissive Service Account IAM Bindings
The second category is service accounts with roles/artifactregistry.writer or roles/artifactregistry.admin bound at the project level rather than the repository level. When a CI/CD pipeline service account has project-level write access to Artifact Registry, any compromise of that pipeline — a supply chain injection, a leaked GitHub Actions secret, a malicious PR — can push a backdoored image that gets deployed across the entire environment.
The correct model is least-privilege repository-scoped bindings:
# Grant a CI service account push access to a specific repository only
gcloud artifacts repositories add-iam-policy-binding REPO_NAME \
--location=us-central1 \
--member="serviceAccount:ci-pipeline@YOUR_PROJECT.iam.gserviceaccount.com" \
--role="roles/artifactregistry.writer" \
--project=YOUR_PROJECT_ID
For GKE workloads pulling images, the node service account needs only roles/artifactregistry.reader, scoped to the specific repository:
gcloud artifacts repositories add-iam-policy-binding REPO_NAME \
--location=us-central1 \
--member="serviceAccount:gke-nodes@YOUR_PROJECT.iam.gserviceaccount.com" \
--role="roles/artifactregistry.reader"
Workload Identity Federation for CI/CD: Service account keys stored in CI systems are a persistent credential leak risk. Replace them with Workload Identity Federation, which issues short-lived OIDC tokens:
# In GitHub Actions
- name: Authenticate to GCP
uses: google-github-actions/auth@v2
with:
workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID'
service_account: 'ci-pipeline@YOUR_PROJECT.iam.gserviceaccount.com'
This eliminates long-lived service account keys entirely. If the CI token is stolen, it’s valid for one hour maximum and cannot be refreshed.
Misconfiguration 3: Secrets Embedded in Container Image Layers
Container images are built in layers, and secrets baked into those layers persist in the registry even after subsequent layers attempt to delete them. This is a common pattern: a Dockerfile copies a credentials file during the build, uses it to pull private dependencies, then runs RUN rm credentials.json — but the file still exists in the earlier layer and is extractable.
# This is insecure — the file persists in the layer history
COPY service-account.json /tmp/service-account.json
RUN gcloud auth activate-service-account --key-file=/tmp/service-account.json
RUN rm /tmp/service-account.json # Does NOT remove from layer history
Scan your images with TruffleHog:
# Scan a Docker image in Artifact Registry for secrets
trufflehog docker \
--image=us-central1-docker.pkg.dev/YOUR_PROJECT/REPO/IMAGE:TAG \
--only-verified
Or use Google’s own Container Analysis (Artifact Analysis) to enable automatic vulnerability and secret scanning:
# Enable Container Scanning API (runs on every push to Artifact Registry)
gcloud services enable containerscanning.googleapis.com
Fix: Use Docker BuildKit secrets for credentials needed during build — these are never written to any layer:
# Mount a secret at build time without writing it to the layer
RUN --mount=type=secret,id=gcp_key \
cat /run/secrets/gcp_key | gcloud auth activate-service-account --key-file=-
Build with:
docker buildx build \
--secret id=gcp_key,src=./service-account.json \
-t us-central1-docker.pkg.dev/YOUR_PROJECT/REPO/IMAGE:TAG .
Additional Controls
VPC Service Controls: Wrap Artifact Registry in a VPC Service Controls perimeter to prevent data exfiltration — this blocks image pulls from outside your defined network boundary, even with valid credentials.
Immutable tags: Enable tag immutability to prevent an attacker with write access from overwriting a known-good image tag with a backdoored version:
gcloud artifacts repositories update REPO_NAME \
--location=us-central1 \
--immutable-tags
Audit log monitoring: Enable Data Access audit logs for Artifact Registry to track all read and write operations. Cloud Logging captures artifactregistry.googleapis.com/storage.* events — alert on writes from unexpected service accounts or during off-hours.
Artifact Registry sits at the centre of most GCP deployment pipelines. A misconfiguration here doesn’t produce a data breach directly — it produces a code execution path into every workload that pulls the compromised image.