Skip to content

Terraform: 7 LOW/MEDIUM Trivy misconfigurations, incl. a public GCS bucket that is now dead #166

Description

@joaquimscosta

Surfaced by the security-scan fix in #165. These are reported to the Security tab but do not block deploys (the gate is HIGH/CRITICAL only), so they need a deliberate decision.

Findings

Severity Location Rule
MEDIUM main.tf:41 GCP-0078 — storage bucket public access
MEDIUM main.tf:41 GCP-0077 — bucket not encrypted with customer-managed key
MEDIUM main.tf:123 GCP-0077
MEDIUM iam.tf:271 GCP-0011
LOW main.tf:41 GCP-0066 — bucket logging not enabled
LOW main.tf:123 GCP-0066
LOW monitoring.tf:129 GCP-0079

The one that matters: main.tf:41 — a public bucket nobody uses

google_storage_bucket.media_storage grants allUsersroles/storage.objectViewer (main.tf:62-70). It is publicly readable.

It is also dead. Media storage migrated to Cloudflare R2 (R2StorageService.kt, R2AdminService.kt); a grep for gcs|google.cloud.storage|storage.googleapis across apps/api/src returns zero hits, and there is no GCS dependency in build.gradle.kts. CLAUDE.md also states GCP media storage is deferred.

So this is a publicly-readable bucket that no code reads from or writes to.

Careful — the dead variable is load-bearing

Removing it is not a one-liner. GCS_BUCKET_NAME is:

  • injected into the backend container (cloudrun.tf:81-84)
  • listed in required_secrets in backend-ci.yml:377, where the loop at :379-387 exit 1s the production deploy if it is missing from the Cloud Run env

So deleting the bucket + env var without also updating backend-ci.yml:377 will break backend deploys.

Also worth noting: required_secrets checks GCS_BUCKET_NAME but does not check any of the R2 / AI / YouTube vars the app actually uses — it is verifying the wrong list.

Suggested change (atomic)

  1. Remove google_storage_bucket.media_storage, the allUsers IAM binding, the objectAdmin grants (iam.tf:215-219, cicd_media_storage_access), the GCS_BUCKET_NAME env var, and the two outputs (outputs.tf:3-6, 93-96)
  2. Remove GCS_BUCKET_NAME from required_secrets in backend-ci.yml:377 in the same commit
  3. Consider adding the R2 vars to required_secrets instead
  4. Keep google_project_service.storage (apis.tf:47) — the Terraform state bucket needs it

The remaining LOW/MEDIUM findings (CMEK, bucket logging) are separate hardening decisions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions