Cloud Security Wire
AWS Azure GCP RSS
GCP Misconfiguration high

GCP Cloud Run Security Misconfigurations: What Goes Wrong and How to Fix It

Cloud Run makes container deployment fast and simple, but the defaults create several exploitable conditions: publicly reachable services with no authentication, overprivileged compute service accounts, secrets in environment variables, and container images that bypass vulnerability scanning. This guide covers each pattern with gcloud remediation.

By Cloud Security Wire · ·
#GCP#Cloud Run#serverless#misconfiguration#IAM#service-accounts#container-security#google-cloud#unauthenticated-access#secret-manager#CSPM
High Severity

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

Cloud Run’s appeal is its simplicity: push a container, get a URL, pay for what you use. That simplicity creates predictable security oversights. Services that should be internal are accidentally made public. Containers run as the default compute service account, which has permissions across the project. Secrets get hardcoded into environment variables because that’s the path of least resistance. Images get deployed without vulnerability scanning.

None of these are exotic vulnerabilities. They’re all documented, they’re all preventable, and they appear in GCP environments regularly because the defaults don’t enforce security.

Unauthenticated Access: The Most Common Cloud Run Misconfiguration

When you deploy a Cloud Run service, you’re presented with a choice: allow unauthenticated invocations or require authentication. The Google Cloud Console defaults to “Allow unauthenticated invocations” for new services. Many teams choose this to avoid dealing with IAM, and it works — the service is accessible publicly with no credentials required.

For public APIs and websites, this is intentional. For internal microservices, backend processors, and admin endpoints, it’s an exposure.

Check all Cloud Run services in a project for unauthenticated access:

gcloud run services list --format="table(metadata.name,status.url,spec.template.metadata.annotations['run.googleapis.com/ingress'])" --project=YOUR_PROJECT

# Find services allowing unauthenticated invocations
gcloud run services describe SERVICE_NAME --region=REGION \
  --format="value(spec.template.metadata.annotations)"

Check IAM policy for a specific service:

gcloud run services get-iam-policy SERVICE_NAME \
  --region=REGION \
  --project=YOUR_PROJECT

If the output includes allUsers or allAuthenticatedUsers in the members field of any binding, the service is publicly accessible.

Restrict to internal or load-balancer-only ingress:

# Internal only (reachable from VPC and Cloud Run services in same project)
gcloud run services update SERVICE_NAME \
  --region=REGION \
  --ingress=internal

# Via load balancer only (requires Cloud Load Balancing IAP or backend service)
gcloud run services update SERVICE_NAME \
  --region=REGION \
  --ingress=internal-and-cloud-load-balancing

Remove allUsers IAM binding:

gcloud run services remove-iam-policy-binding SERVICE_NAME \
  --region=REGION \
  --member="allUsers" \
  --role="roles/run.invoker"

For services that must be publicly accessible but only to authenticated callers, require Google identity tokens:

gcloud run services remove-iam-policy-binding SERVICE_NAME \
  --region=REGION \
  --member="allUsers" \
  --role="roles/run.invoker"

# Then add specific identities, groups, or service accounts as invokers
gcloud run services add-iam-policy-binding SERVICE_NAME \
  --region=REGION \
  --member="serviceAccount:backend-sa@YOUR_PROJECT.iam.gserviceaccount.com" \
  --role="roles/run.invoker"

Overprivileged Service Accounts

When a Cloud Run service doesn’t have an explicitly assigned service account, it runs as the Compute Engine default service account ([email protected]). This account has the Editor role on the project by default — a role that grants read and write access to virtually all GCP APIs.

A Cloud Run service running as the default compute service account can read and write to all Cloud Storage buckets, deploy new Cloud Functions and Cloud Run services, modify Cloud SQL databases, access Secret Manager secrets, and read other services’ service account keys. If the container is compromised, the attacker has effective admin access to the GCP project.

Audit which service account each Cloud Run service uses:

gcloud run services list --format="table(metadata.name,spec.template.spec.serviceAccountName)" \
  --project=YOUR_PROJECT

Any service showing <PROJECT_NUMBER>[email protected] is running as the default account and should be reviewed.

Create a dedicated least-privilege service account for each Cloud Run service:

# Create a dedicated SA
gcloud iam service-accounts create cloud-run-myservice \
  --display-name="Cloud Run MyService SA" \
  --project=YOUR_PROJECT

# Grant only the permissions the service needs
# Example: read-only access to a specific GCS bucket
gcloud storage buckets add-iam-policy-binding gs://my-data-bucket \
  --member="serviceAccount:cloud-run-myservice@YOUR_PROJECT.iam.gserviceaccount.com" \
  --role="roles/storage.objectViewer"

# Assign the SA to the Cloud Run service
gcloud run services update SERVICE_NAME \
  --region=REGION \
  --service-account=cloud-run-myservice@YOUR_PROJECT.iam.gserviceaccount.com

Also consider removing the default Editor role from the compute service account:

# Remove Editor from default compute SA
gcloud projects remove-iam-policy-binding YOUR_PROJECT \
  --member="serviceAccount:[email protected]" \
  --role="roles/editor"

This will break anything that relies on it — audit dependencies first.

Secrets in Environment Variables

Cloud Run makes it trivially easy to pass secrets as environment variables:

gcloud run deploy SERVICE_NAME \
  --set-env-vars="DB_PASSWORD=supersecret123,API_KEY=abc123"

This is a persistent mistake because those secrets are then visible in:

  • The Cloud Run service configuration (accessible via gcloud run services describe)
  • Cloud Console to anyone with run.services.get permission
  • Container runtime environment, which can be read by any code in the container
  • Audit logs if the service was deployed with those values

Audit environment variables for secrets:

gcloud run services describe SERVICE_NAME \
  --region=REGION \
  --format="yaml(spec.template.spec.containers[0].env)"

Look for keys like PASSWORD, SECRET, KEY, TOKEN, CREDENTIAL, PRIVATE.

Move secrets to Secret Manager and mount them:

# Create the secret
echo -n "supersecret123" | \
  gcloud secrets create DB_PASSWORD \
  --data-file=- \
  --project=YOUR_PROJECT

# Grant the Cloud Run service account access to the secret
gcloud secrets add-iam-policy-binding DB_PASSWORD \
  --member="serviceAccount:cloud-run-myservice@YOUR_PROJECT.iam.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"

# Mount the secret as an env var in Cloud Run
gcloud run services update SERVICE_NAME \
  --region=REGION \
  --set-secrets="DB_PASSWORD=DB_PASSWORD:latest"

Secret Manager mounts deliver the secret value at runtime without it appearing in the service configuration or audit logs for environment variable access.

Container Image Security: Scanning and Provenance

Cloud Run will deploy any container image you point it at. Without scanning, there’s no check on whether that image contains known vulnerabilities in its base layer or installed packages.

Enable Artifact Registry Vulnerability Scanning:

# Enable the Container Scanning API
gcloud services enable containerscanning.googleapis.com

# Vulnerability scanning is automatically enabled for images pushed to Artifact Registry
# View scan results for an image
gcloud artifacts docker images list REGION-docker.pkg.dev/PROJECT/REPO \
  --include-tags \
  --format="table(IMAGE, TAGS, DIGEST)"

gcloud artifacts docker images describe \
  REGION-docker.pkg.dev/PROJECT/REPO/IMAGE:TAG \
  --show-package-vulnerability

Block deployment of images with critical vulnerabilities (Binary Authorization):

Binary Authorization allows you to enforce image attestation policies, blocking deployment unless the image has been scanned and meets your vulnerability threshold:

# Enable Binary Authorization
gcloud services enable binaryauthorization.googleapis.com

# Create a policy requiring scan attestation
cat > policy.yaml << 'EOF'
admissionWhitelistPatterns:
- namePattern: gcr.io/google-containers/*
- namePattern: gcr.io/google_containers/*
defaultAdmissionRule:
  evaluationMode: REQUIRE_ATTESTATION
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
  requireAttestationsBy:
  - projects/YOUR_PROJECT/attestors/vulnerability-scan-attestor
name: projects/YOUR_PROJECT/policy
EOF

gcloud container binauthz policy import policy.yaml --project=YOUR_PROJECT

VPC Egress and Network Isolation

Cloud Run services can reach the public internet by default. For services handling sensitive data or performing backend operations, consider restricting egress:

# Route all egress through VPC (requires Serverless VPC Access connector)
gcloud run services update SERVICE_NAME \
  --region=REGION \
  --vpc-egress=all-traffic \
  --vpc-connector=projects/PROJECT/locations/REGION/connectors/CONNECTOR_NAME

Combined with VPC firewall rules, this ensures all outbound traffic from the container goes through your network controls and logging infrastructure.

Org Policy: Enforce Secure Defaults Across Projects

For organisations managing multiple GCP projects, enforce Cloud Run security policies at the organisation or folder level:

# Require HTTPS only (disable HTTP on Cloud Run services)
gcloud resource-manager org-policies enable-enforce \
  --organization=ORG_ID \
  constraints/run.allowedIngress

# Restrict which regions Cloud Run can be deployed to
gcloud resource-manager org-policies set-policy \
  --organization=ORG_ID \
  region-restriction-policy.yaml

The constraints/iam.disableServiceAccountKeyCreation org policy, combined with mandatory workload identity for Cloud Run, eliminates the service account key sprawl risk entirely across all projects.

Reviewed regularly — at minimum on any new Cloud Run service deployment — these controls collectively address the principal attack surface Cloud Run exposes. The highest priority items are unauthenticated access and default service account usage: both produce immediate, substantial risk and both are fixable in under ten minutes.

← All Analysis Subscribe via RSS