Fix GCP Cloud Storage '403 Forbidden' Errors
The Error: "403 Forbidden" on Cloud Storage
You try to access a GCS object and get:
AccessDeniedException: 403 [email protected] does not have
storage.objects.get access to the Google Cloud Storage object.
Or from gsutil:
ServiceException: 403 Forbidden
You know the bucket exists and the object is there, but GCP won't let you in.
Root Cause
GCP Cloud Storage access is controlled by IAM policies and, on older buckets, ACLs. Common causes of 403 errors:
- Missing IAM role on the service account or user
- Wrong project context -- authenticated to a different project
- Uniform bucket-level access enabled, making ACLs irrelevant
- VPC Service Controls blocking access from outside the perimeter
- Requester Pays enabled but the requester didn't provide a billing project
Step-by-Step Fix
1. Identify Who You Are
gcloud auth list
# Shows the active account
gcloud config get-value project
# Shows the active project
For service accounts in GKE or Compute Engine:
curl -H "Metadata-Flavor: Google" \
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email
2. Check Your Current Permissions
# Test if you can list objects
gsutil ls gs://my-bucket/
# Test a specific object
gsutil stat gs://my-bucket/my-object.txt
3. Check Bucket IAM Policy
gsutil iam get gs://my-bucket/
Or with gcloud:
gcloud storage buckets get-iam-policy gs://my-bucket/ --format=json
Look for your service account or user in the bindings. You need at minimum:
roles/storage.objectViewer-- to read objectsroles/storage.objectAdmin-- to read, write, and delete objects
4. Grant the Required Role
# Grant object viewer to a service account
gsutil iam ch \
serviceAccount:[email protected]:objectViewer \
gs://my-bucket/
# Or using gcloud for project-level access
gcloud projects add-iam-policy-binding my-project \
--member="serviceAccount:[email protected]" \
--role="roles/storage.objectViewer"
5. Check for Uniform Bucket-Level Access
gsutil uniformbucketlevelaccess get gs://my-bucket/
If enabled, ACLs are ignored and only IAM policies matter. This is the recommended setting, but it means you can't use gsutil acl commands.
6. Handle Cross-Project Access
If the bucket is in a different project, you need to grant permissions explicitly:
# In the project that OWNS the bucket
gsutil iam ch \
serviceAccount:[email protected]:objectViewer \
gs://my-bucket/
7. Check VPC Service Controls
If your organization uses VPC Service Controls:
gcloud access-context-manager perimeters list \
--policy=POLICY_ID --format="table(name,status.resources)"
If the bucket's project is inside a perimeter, requests from outside are blocked with 403. You need to either:
- Make the request from inside the perimeter (e.g., from a VM in the project)
- Add an ingress rule to the perimeter
8. Handle Requester Pays Buckets
If the bucket has Requester Pays enabled:
# This fails
gsutil cat gs://requester-pays-bucket/file.txt
# This works -- specify a billing project
gsutil -u my-billing-project cat gs://requester-pays-bucket/file.txt
9. Verify the Fix
gsutil cat gs://my-bucket/my-object.txt
# Should return the file contents
# Or test with a simple list
gsutil ls gs://my-bucket/
Prevention Tips
- Use Workload Identity in GKE instead of JSON key files. It eliminates key management headaches and automatically scopes permissions.
- Apply least privilege using predefined roles like
roles/storage.objectViewerinstead ofroles/storage.admin. - Enable uniform bucket-level access on all buckets so permissions are managed in one place (IAM), not two (IAM + ACLs).
- Use
gcloud policy-troubleshootto debug access issues:gcloud policy-troubleshoot iam gs://bucket --permission=storage.objects.get [email protected]. - Audit IAM bindings with Cloud Asset Inventory to catch overly permissive or missing roles.
Was this article helpful?
DevSecOps Lead
Security-first mindset in everything I ship. From zero-trust architectures to supply chain security, I make sure your pipeline doesn't become your weakest link.
Related Articles
GCP Cloud Function "Function Execution Took Too Long" Error: Memory And Timeout Configuration Fix Guide
Getting the dreaded "Function execution took too long" error in your Cloud Functions? You're not alone. This error happens when your function exceeds the c...
GCP Core Services: The DevOps Engineer's Essential Guide
Learn GCP's core services — Compute Engine, GKE, Cloud Storage, VPC, IAM, Cloud Build, and Cloud Run for modern DevOps workflows.
GKE Autopilot: Serverless Kubernetes on Google Cloud
Deploy production workloads on GKE Autopilot — serverless Kubernetes with automatic node management, security, and scaling.
Google Cloud Run: Serverless Containers That Scale to Zero
Deploy and manage containerized workloads on Google Cloud Run — no infrastructure to manage. Covers service configuration, traffic splitting, secrets, VPC connectivity, Cloud Run Jobs, and cost optimization.
Google GKE: Production Kubernetes Cluster on Google Cloud
Launch a production GKE cluster on Google Cloud Platform — Autopilot vs Standard mode, node pools, Workload Identity, Binary Authorization, GKE Dataplane V2, private clusters, and Terraform configuration.
Google Cloud Build: CI/CD Pipelines for GCP-Native Teams
Build, test, and deploy containerized apps with Google Cloud Build — triggers, substitutions, private pools, and GKE integration.