Skip to content

Secrets pasted into plain env vars

A credential set as a plain Cloud Run env var is stored in plaintext on the revision and readable by anyone with run.services.get, so it leaks through the service definition rather than through an attack.

see_it · fix_it

The misconfig, then the fix

Each verdict below is the actual Cloud Run Config Auditor run on the snippet, not a description of one.

before
gcloud run deploy api \
  --image=gcr.io/my-project/api \
  --region=us-central1 \
  --set-env-vars=API_KEY=sk-live-abc123,DB_PASSWORD=hunter2

Fails · auditor verdictSecret-looking value(s) set as plain env vars: API_KEY, DB_PASSWORD. Env vars on a Cloud Run revision are visible to anyone with run.services.get and are stored in plaintext on the revision. Move them to Secret Manager and mount with --set-secrets so the value is never in the service definition.

after
gcloud run deploy api \
  --image=gcr.io/my-project/api \
  --region=us-central1 \
  --set-secrets=API_KEY=api-key:latest,DB_PASSWORD=db-password:latest

Passes · auditor verdictSensitive config comes from Secret Manager (2 secret refs), so the value never lives in the revision spec. Keep non-secret config in env vars and secrets here.

fix · --set-secrets=API_KEY=my-api-key:latest,DB_PASSWORD=db-password:latest

why_it_matters

Cloud Run env vars are convenient and they're plaintext. Whatever you pass to --set-env-vars is stored on the revision spec and visible to anyone who can describe the service, which is a much wider set of principals than you'd grant access to a secret. An API key or database password among those env vars is a credential sitting in your deploy config, in your shell history, and in whatever CI logs ran the command.

Move secrets to Secret Manager and mount them with --set-secrets, so the revision holds a reference, not the value, and access is governed by Secret Manager IAM. Keep plain env vars for genuinely non-secret config. The auditor fails a deploy when a secret-looking key (API_KEY, DB_PASSWORD, and similar) appears in --set-env-vars, and passes it once those move to --set-secrets.

--set-env-vars=API_KEY=…plaintext on the revision--set-secrets mounts from Secret Manager

faq

Questions & answers

Are Cloud Run environment variables secure for secrets?
No. Env vars set with --set-env-vars are stored in plaintext on the revision and readable by anyone with run.services.get. Use Secret Manager and --set-secrets so the revision holds only a reference and access is controlled by Secret Manager IAM.
How do I use Secret Manager with Cloud Run?
Store the value in Secret Manager, then mount it at deploy with --set-secrets=ENV_NAME=secret-name:latest. The container sees it as an env var, but the value never lives in the service definition, and you can rotate it in Secret Manager without redeploying config into your shell history.

Fixing one binding is easy. Getting the whole project to least privilege is the work.

I review which principals hold primitive and escalation roles, how your workloads are scoped, secrets handling, and the Cloud Run defaults that widen the blast radius. Book a call, or leave your email.

Book a call

No spam. You'll get a reply from me.

Prefer proof first? See how this plays out in real case studies →