Built-in scenario

gcp/sample_gcp_nightmare_plan.json

GCP Nightmare Plan Demo

Analyzed sample_gcp_nightmare_plan.json with 31 normalized resources and 9 trust boundaries.

Analyze another plan

Active findings

45

Trust boundaries

9

Resources

31

Observations

0
High 14
Medium 29
Low 2

Analysis coverage

Audit trail for this run

Terraform resources 31
Unsupported 0
Enabled rules 78
Unresolved refs 0

Resource coverage

Provider resources considered
31
Normalized resources
31

No unsupported GCP resource types were encountered.

Rule coverage

Registered rules
78
Disabled rules
0
  • gcp-sensitive-resource-iam-external-access2
  • gcp-pubsub-public-access1
  • gcp-pubsub-topic-customer-managed-encryption-missing1
  • gcp-pubsub-subscription-dead-letter-policy-missing1
  • gcp-bigquery-public-access1
  • gcp-cloud-sql-public-authorized-network1
  • gcp-cloud-sql-backup-disabled1
  • gcp-cloud-sql-public-ip-without-private-network1
  • gcp-cloud-sql-ssl-not-required1
  • gcp-cloud-sql-deletion-protection-disabled1
  • gcp-cloud-sql-zonal-availability1
  • gcp-gcs-public-access1
  • gcp-gcs-public-access-prevention-not-enforced1
  • gcp-gcs-versioning-disabled1
  • gcp-gcs-customer-managed-encryption-missing1
  • gcp-gcs-retention-policy-insufficient1
  • gcp-secret-manager-customer-managed-encryption-missing1
  • gcp-secret-manager-lifecycle-posture-incomplete1
  • gcp-public-compute-broad-ingress1
  • gcp-compute-os-login-disabled1
  • gcp-gke-public-control-plane1
  • gcp-gke-broad-authorized-networks1
  • gcp-gke-workload-identity-disabled1
  • gcp-gke-legacy-metadata-endpoints-enabled1
  • gcp-gke-broad-node-service-account1
  • gcp-gke-control-plane-logging-incomplete1
  • gcp-subnetwork-flow-logs-not-configured1
  • gcp-gke-network-policy-disabled1
  • gcp-gke-secrets-encryption-not-configured1
  • gcp-gke-legacy-abac-enabled-or-unknown1
  • gcp-gke-shielded-nodes-disabled-or-unknown1
  • gcp-cloud-run-public-invoker1
  • gcp-cloud-functions-public-invoker1
  • gcp-service-account-key-hygiene1
  • gcp-service-account-key-effective-access1
  • gcp-org-folder-iam-broad-principal1
  • gcp-org-folder-iam-privileged-role1
  • gcp-project-iam-broad-principal1
  • gcp-project-iam-privileged-role1
  • gcp-inherited-iam-sensitive-resource-access1
  • gcp-inherited-iam-blast-radius1
  • gcp-public-workload-sensitive-data-access3

Findings

Severity bands

High

14

BigQuery IAM binding allows public or broad data access

gcp-bigquery-public-access

google_bigquery_dataset.analytics grants `roles/bigquery.dataViewer` to `allUsers` through BigQuery IAM. Public or broad principals can read or modify analytical data outside the expected project trust boundary.

Category
Information Disclosure
Boundary
not-applicable
Resources
google_bigquery_dataset.analytics, google_bigquery_dataset_iam_binding.analytics_viewers
Evidence
  • iam binding: source=google_bigquery_dataset_iam_binding.analytics_viewers; role=roles/bigquery.dataViewer; member=allUsers
  • trust scope: member is public GCP principal `allUsers`
  • resource policy sources: google_bigquery_dataset_iam_binding.analytics_viewers

Cloud SQL instance accepts public authorized network access

gcp-cloud-sql-public-authorized-network

google_sql_database_instance.app has a public Cloud SQL IPv4 endpoint and an authorized network that allows internet-wide client sources. That weakens the database trust boundary even when database authentication is still required.

Category
Information Disclosure
Boundary
internet-to-service:internet->google_sql_database_instance.app
Resources
google_sql_database_instance.app
Evidence
  • authorized networks: anywhere (0.0.0.0/0)
  • public exposure reasons: authorized network `anywhere` allows 0.0.0.0/0

GCP organization or folder IAM grants a high-privilege role

gcp-org-folder-iam-privileged-role

google_folder_iam_member.folder_admin grants the high-impact GCP role `roles/resourcemanager.folderAdmin` to `group:folder-admins@example.com` at folder scope `folders/12345`. That role enables folder hierarchy administration across a high-level resource boundary and can materially expand blast radius if the principal is compromised.

Category
Elevation of Privilege
Boundary
not-applicable
Resources
google_folder_iam_member.folder_admin
Evidence
  • iam binding: member=group:folder-admins@example.com; role=roles/resourcemanager.folderAdmin
  • scope: folder scope `folders/12345`
  • role risk: folder hierarchy administration

GCP organization or folder IAM grants access to broad principals

gcp-org-folder-iam-broad-principal

google_organization_iam_binding.domain_viewer grants `roles/viewer` to `domain:example.com` at organization scope `1234567890`. Public or broad-domain principals at organization or folder scope can expand access across many descendant projects and workloads.

Category
Elevation of Privilege
Boundary
not-applicable
Resources
google_organization_iam_binding.domain_viewer
Evidence
  • iam binding: member=domain:example.com; role=roles/viewer
  • scope: organization scope `1234567890`
  • trust scope: member grants a whole Google Workspace domain

GCP project IAM binding grants a high-privilege role

gcp-project-iam-privileged-role

google_project_iam_member.public_owner grants the high-impact GCP role `roles/owner` to `allUsers` at project scope. That role enables full project administration and can materially expand control-plane blast radius if the principal is compromised or mis-scoped.

Category
Elevation of Privilege
Boundary
not-applicable
Resources
google_project_iam_member.public_owner
Evidence
  • iam binding: member=allUsers; role=roles/owner
  • role risk: full project administration

GCP service account key can exercise sensitive or privileged access

gcp-service-account-key-effective-access

google_service_account_key.web creates portable credentials for `google_service_account.web`, and that service account has sensitive data access or high-impact IAM grants. A copied key can exercise those effective permissions outside the intended workload boundary.

Category
Elevation of Privilege
Boundary
not-applicable
Resources
google_service_account.web, google_service_account_key.web, google_bigquery_dataset.analytics, google_bigquery_dataset_iam_binding.analytics_viewers
Evidence
  • key context: source=google_service_account_key.web; service_account_reference=google_service_account.web.email; resolved_service_account=google_service_account.web
  • service account principals: serviceAccount:tfstride-web@example.iam.gserviceaccount.com; tfstride-web@example.iam.gserviceaccount.com
  • effective access: resource=google_bigquery_dataset.analytics; source=google_bigquery_dataset_iam_binding.analytics_viewers; scope=BigQuery dataset IAM; role=roles/bigquery.dataViewer; member=serviceAccount:tfstride-web@example.iam.gserviceaccount.com; risk=BigQuery dataset IAM grants roles/bigquery.dataViewer

GKE node pool uses broad node identity settings

gcp-gke-broad-node-service-account

google_container_node_pool.app uses broad GKE node identity settings. Default or broadly scoped node service accounts can turn a node or pod compromise into wider GCP API access.

Category
Elevation of Privilege
Boundary
not-applicable
Resources
google_container_node_pool.app
Evidence
  • node identity risks: node service account uses default Compute Engine identity `123456789-compute@developer.gserviceaccount.com`; node OAuth scope is broad: https://www.googleapis.com/auth/cloud-platform
  • node service account: 123456789-compute@developer.gserviceaccount.com
  • oauth scopes: https://www.googleapis.com/auth/cloud-platform

Inherited GCP IAM grant expands descendant blast radius

gcp-inherited-iam-blast-radius

google_project_iam_member.public_owner grants `roles/owner` to `allUsers` at project scope `tfstride-demo`, and that inherited grant applies to 21 concrete descendant resource(s). A high-level IAM grant with broad, external, or high-impact access increases control-plane blast radius because compromise or misuse can affect resources below the inherited scope.

Category
Elevation of Privilege
Boundary
not-applicable
Resources
google_project_iam_member.public_owner, google_bigquery_dataset.analytics, google_bigquery_table.events, google_cloud_run_v2_service.api, google_cloudfunctions_function.worker, google_compute_firewall.public_admin, google_compute_firewall.public_all, google_compute_instance.web, google_compute_network.main, google_compute_route.default_internet, google_compute_subnetwork.app, google_container_cluster.app, google_container_node_pool.app, google_kms_crypto_key.customer, google_logging_project_sink.processor, google_pubsub_subscription.events, google_pubsub_topic.events, google_secret_manager_secret.api_key, google_service_account.web, google_service_account_key.web, google_sql_database_instance.app, google_storage_bucket.logs
Evidence
  • iam binding: source=google_project_iam_member.public_owner; scope=project:tfstride-demo; member=allUsers; role=roles/owner
  • role risk: full project administration
  • trust scope: member is public GCP principal `allUsers`
  • descendant scope: scope=project:tfstride-demo; descendant_count=21; resource_type_count=20; projects=tfstride-demo
  • descendant resource types: google_bigquery_dataset: 1; google_bigquery_table: 1; google_cloud_run_v2_service: 1; google_cloudfunctions_function: 1; google_compute_firewall: 2; google_compute_instance: 1; google_compute_network: 1; google_compute_route: 1; google_compute_subnetwork: 1; google_container_cluster: 1; google_container_node_pool: 1; google_kms_crypto_key: 1; google_logging_project_sink: 1; google_pubsub_subscription: 1; google_pubsub_topic: 1; google_secret_manager_secret: 1; google_service_account: 1; google_service_account_key: 1; google_sql_database_instance: 1; google_storage_bucket: 1
  • descendant resources: google_bigquery_dataset.analytics; google_bigquery_table.events; google_cloud_run_v2_service.api; google_cloudfunctions_function.worker; google_compute_firewall.public_admin; google_compute_firewall.public_all; google_compute_instance.web; google_compute_network.main; google_compute_route.default_internet; google_compute_subnetwork.app; and 11 more descendant resources

Inherited GCP IAM grant reaches sensitive resources

gcp-inherited-iam-sensitive-resource-access

google_project_iam_member.public_owner grants `roles/owner` to `allUsers` at project scope `tfstride-demo`, and that inherited grant reaches 8 sensitive GCP descendant resource(s). Project, folder, and organization IAM applies below the grant scope, so a single ancestor binding can expose data resources beyond their local IAM boundary.

Category
Information Disclosure
Boundary
not-applicable
Resources
google_project_iam_member.public_owner, google_bigquery_dataset.analytics, google_bigquery_table.events, google_kms_crypto_key.customer, google_pubsub_subscription.events, google_pubsub_topic.events, google_secret_manager_secret.api_key, google_sql_database_instance.app, google_storage_bucket.logs
Evidence
  • iam binding: source=google_project_iam_member.public_owner; scope=project:tfstride-demo; member=allUsers; role=roles/owner
  • sensitive descendants: resource=google_bigquery_dataset.analytics; type=google_bigquery_dataset; risk=BigQuery dataset data access through roles/owner; resource=google_bigquery_table.events; type=google_bigquery_table; risk=BigQuery table data access through roles/owner; resource=google_kms_crypto_key.customer; type=google_kms_crypto_key; risk=Cloud KMS cryptographic key access through roles/owner; resource=google_pubsub_subscription.events; type=google_pubsub_subscription; risk=Pub/Sub subscription data access through roles/owner; resource=google_pubsub_topic.events; type=google_pubsub_topic; risk=Pub/Sub topic data access through roles/owner; resource=google_secret_manager_secret.api_key; type=google_secret_manager_secret; risk=Secret Manager secret access through roles/owner; resource=google_sql_database_instance.app; type=google_sql_database_instance; risk=Cloud SQL client/admin access through roles/owner; resource=google_storage_bucket.logs; type=google_storage_bucket; risk=GCS object data access through roles/owner
  • trust scope: member is public GCP principal `allUsers`

Internet-exposed GCP workload can access sensitive data services

gcp-public-workload-sensitive-data-access

google_cloud_run_v2_service.api is internet-exposed and runs with GCP workload identity serviceAccount:tfstride-run@tfstride-demo.iam.gserviceaccount.com. That identity can access google_sql_database_instance.app. A compromise of the public workload can therefore become direct access to sensitive GCP data services.

Category
Information Disclosure
Boundary
workload-to-data-store:google_cloud_run_v2_service.api->google_sql_database_instance.app
Resources
google_cloud_run_v2_service.api, google_sql_database_instance.app
Evidence
  • public exposure reasons: google_cloud_run_v2_service_iam_member.public_invoker grants roles/run.invoker to allUsers
  • workload identity: serviceAccount:tfstride-run@tfstride-demo.iam.gserviceaccount.com
  • data access path: google_cloud_run_v2_service.api reaches google_sql_database_instance.app
  • boundary rationale: Application or function workloads cross into a higher-sensitivity data plane when a directly internet-reachable database is reachable from a workload subnet with general egress.

Internet-exposed GCP workload can access sensitive data services

gcp-public-workload-sensitive-data-access

google_cloudfunctions_function.worker is internet-exposed and runs with GCP workload identity serviceAccount:tfstride-fn@tfstride-demo.iam.gserviceaccount.com. That identity can access google_sql_database_instance.app. A compromise of the public workload can therefore become direct access to sensitive GCP data services.

Category
Information Disclosure
Boundary
workload-to-data-store:google_cloudfunctions_function.worker->google_sql_database_instance.app
Resources
google_cloudfunctions_function.worker, google_sql_database_instance.app
Evidence
  • public exposure reasons: google_cloudfunctions_function_iam_member.public_invoker grants roles/cloudfunctions.invoker to allAuthenticatedUsers
  • workload identity: serviceAccount:tfstride-fn@tfstride-demo.iam.gserviceaccount.com
  • data access path: google_cloudfunctions_function.worker reaches google_sql_database_instance.app
  • boundary rationale: Application or function workloads cross into a higher-sensitivity data plane when a directly internet-reachable database is reachable from a workload subnet with general egress.

Internet-exposed GCP workload can access sensitive data services

gcp-public-workload-sensitive-data-access

google_compute_instance.web is internet-exposed and runs with GCP workload identity serviceAccount:tfstride-web@example.iam.gserviceaccount.com. That identity can access google_bigquery_dataset.analytics. A compromise of the public workload can therefore become direct access to sensitive GCP data services.

Category
Information Disclosure
Boundary
workload-to-data-store:google_compute_instance.web->google_bigquery_dataset.analytics
Resources
google_compute_instance.web, google_bigquery_dataset.analytics, google_bigquery_dataset_iam_binding.analytics_viewers
Evidence
  • public exposure reasons: compute instance has an external access config and matching firewall rules allow internet ingress
  • workload identity: serviceAccount:tfstride-web@example.iam.gserviceaccount.com
  • workload identity scopes: cloud-platform
  • data access path: google_compute_instance.web reaches google_bigquery_dataset.analytics
  • boundary rationale: GCP workloads cross into a higher-sensitivity data plane when their attached service account is granted data access through IAM: google_bigquery_dataset_iam_binding.analytics_viewers grants roles/bigquery.dataViewer to serviceAccount:tfstride-web@example.iam.gserviceaccount.com.
  • resource policy sources: google_bigquery_dataset_iam_binding.analytics_viewers

Pub/Sub IAM binding allows public or broad data access

gcp-pubsub-public-access

google_pubsub_topic.events grants `roles/pubsub.publisher` to `allAuthenticatedUsers` through Pub/Sub IAM. Public or broad principals can publish, consume, or administer event streams outside the expected service boundary.

Category
Information Disclosure
Boundary
not-applicable
Resources
google_pubsub_topic.events, google_pubsub_topic_iam_member.public_publisher
Evidence
  • iam binding: source=google_pubsub_topic_iam_member.public_publisher; role=roles/pubsub.publisher; member=allAuthenticatedUsers
  • trust scope: member is public GCP principal `allAuthenticatedUsers`
  • resource policy sources: google_pubsub_topic_iam_member.public_publisher

Sensitive GCP resource IAM binding allows broad or external access

gcp-sensitive-resource-iam-external-access

google_secret_manager_secret.api_key grants `roles/secretmanager.secretAccessor` to `allAuthenticatedUsers` through GCP IAM. Public, broad-domain, or foreign-project principals can access sensitive secrets or cryptographic key operations outside the expected project trust boundary.

Category
Information Disclosure
Boundary
not-applicable
Resources
google_secret_manager_secret.api_key, google_secret_manager_secret_iam_member.public_accessor
Evidence
  • iam binding: source=google_secret_manager_secret_iam_member.public_accessor; role=roles/secretmanager.secretAccessor; member=allAuthenticatedUsers
  • trust scope: member is public GCP principal `allAuthenticatedUsers`
  • resource policy sources: google_secret_manager_secret_iam_member.public_accessor

Medium

29

Cloud Functions function is publicly invokable

gcp-cloud-functions-public-invoker

google_cloudfunctions_function.worker allows public HTTP access and grants Cloud Functions invoke permission to public GCP principals. Unauthenticated internet clients can reach the function entry point without an organization-owned identity boundary.

Category
Spoofing
Boundary
internet-to-service:internet->google_cloudfunctions_function.worker
Resources
google_cloudfunctions_function.worker, google_cloudfunctions_function_iam_member.public_invoker
Evidence
  • public invoker bindings: source=google_cloudfunctions_function_iam_member.public_invoker; role=roles/cloudfunctions.invoker; member=allAuthenticatedUsers
  • public access reasons: google_cloudfunctions_function_iam_member.public_invoker grants roles/cloudfunctions.invoker to allAuthenticatedUsers
  • public exposure reasons: google_cloudfunctions_function_iam_member.public_invoker grants roles/cloudfunctions.invoker to allAuthenticatedUsers

Cloud Run service is publicly invokable

gcp-cloud-run-public-invoker

google_cloud_run_v2_service.api allows public ingress and grants Cloud Run invoke permission to public GCP principals. Unauthenticated internet clients can reach the service entry point without an organization-owned identity boundary.

Category
Spoofing
Boundary
internet-to-service:internet->google_cloud_run_v2_service.api
Resources
google_cloud_run_v2_service.api, google_cloud_run_v2_service_iam_member.public_invoker
Evidence
  • public invoker bindings: source=google_cloud_run_v2_service_iam_member.public_invoker; role=roles/run.invoker; member=allUsers
  • public access reasons: google_cloud_run_v2_service_iam_member.public_invoker grants roles/run.invoker to allUsers
  • public exposure reasons: google_cloud_run_v2_service_iam_member.public_invoker grants roles/run.invoker to allUsers

Cloud SQL automated backups are disabled

gcp-cloud-sql-backup-disabled

google_sql_database_instance.app does not have Cloud SQL automated backups enabled. A destructive change, operator error, or data corruption event would have fewer managed recovery points.

Category
Denial of Service
Boundary
not-applicable
Resources
google_sql_database_instance.app
Evidence
  • backup posture: backup_configuration.enabled is false; point_in_time_recovery_enabled is false; engine is POSTGRES_15

Cloud SQL deletion protection is disabled

gcp-cloud-sql-deletion-protection-disabled

google_sql_database_instance.app has Cloud SQL deletion protection disabled. Accidental or unauthorized infrastructure changes could destroy the managed database instance without this provider-level guardrail.

Category
Denial of Service
Boundary
not-applicable
Resources
google_sql_database_instance.app
Evidence
  • lifecycle posture: deletion_protection is false

Cloud SQL instance uses zonal availability

gcp-cloud-sql-zonal-availability

google_sql_database_instance.app uses zonal Cloud SQL availability. A zonal failure or maintenance disruption can leave the database unavailable longer than a regional high-availability deployment.

Category
Denial of Service
Boundary
not-applicable
Resources
google_sql_database_instance.app
Evidence
  • availability posture: availability_type=ZONAL; engine=POSTGRES_15

Cloud SQL public IPv4 is enabled without private network access

gcp-cloud-sql-public-ip-without-private-network

google_sql_database_instance.app has Cloud SQL public IPv4 enabled without a private network attachment. That keeps database client access on a public endpoint instead of an internal VPC path.

Category
Information Disclosure
Boundary
internet-to-service:internet->google_sql_database_instance.app
Resources
google_sql_database_instance.app
Evidence
  • network posture: ipv4_enabled is true; private_network is unset; authorized_networks configured: 1
  • public access reasons: Cloud SQL public IPv4 access is enabled

Cloud SQL public client access does not require SSL

gcp-cloud-sql-ssl-not-required

google_sql_database_instance.app allows Cloud SQL public IPv4 client access without requiring encrypted client connections. Credentials and database traffic should not depend on client-side optional TLS behavior.

Category
Information Disclosure
Boundary
internet-to-service:internet->google_sql_database_instance.app
Resources
google_sql_database_instance.app
Evidence
  • ssl posture: require_ssl is false; ssl_mode is unset; ipv4_enabled is true

GCP compute instance disables OS Login

gcp-compute-os-login-disabled

google_compute_instance.web explicitly disables OS Login. SSH access can therefore fall back to instance or project metadata keys instead of centralized IAM-backed login and audit controls.

Category
Elevation of Privilege
Boundary
not-applicable
Resources
google_compute_instance.web
Evidence
  • os login posture: metadata.enable-oslogin is false
  • public exposure reasons: compute instance has an external access config and matching firewall rules allow internet ingress

GCP project IAM binding grants access to public principals

gcp-project-iam-broad-principal

google_project_iam_member.public_owner grants `roles/owner` to `allUsers` at project scope. Public or broadly authenticated principals can cross into the control plane without an organization-owned identity boundary.

Category
Elevation of Privilege
Boundary
not-applicable
Resources
google_project_iam_member.public_owner
Evidence
  • iam binding: member=allUsers; role=roles/owner

GCP service account user-managed key lacks rotation hygiene

gcp-service-account-key-hygiene

google_service_account_key.web creates a user-managed GCP service account key for `google_service_account.web`. User-managed service account keys are portable, long-lived credentials that can be copied outside GCP control, so they need explicit rotation controls or should be replaced with workload identity or impersonation flows.

Category
Spoofing
Boundary
not-applicable
Resources
google_service_account.web, google_service_account_key.web
Evidence
  • key context: source=google_service_account_key.web; service_account_reference=google_service_account.web.email; key_algorithm=KEY_ALG_RSA_2048; public_key_type=TYPE_X509_PEM_FILE
  • key risk: Terraform manages a user-created service-account key; validity window is 365 days and exceeds 180-day threshold; no Terraform keepers rotation trigger observed
  • validity window: valid_after=2026-01-01T00:00:00Z; valid_before=2027-01-01T00:00:00Z; validity_days=365
  • rotation control: no Terraform keepers rotation trigger observed

GCP subnetwork Flow Logs are not configured

gcp-subnetwork-flow-logs-not-configured

google_compute_subnetwork.app does not configure VPC Flow Logs in this Terraform plan. Without subnetwork flow telemetry, network investigation, lateral-movement review, and egress analysis can lack packet-flow evidence for workloads attached to this subnet.

Category
Repudiation
Boundary
not-applicable
Resources
google_compute_subnetwork.app
Evidence
  • subnetwork flow log posture: address=google_compute_subnetwork.app; type=google_compute_subnetwork; name=app; identifier=tfstride-app; flow_log_state=not_configured; network=google_compute_network.main.id; project=tfstride-demo

GCS bucket does not enforce Public Access Prevention

gcp-gcs-public-access-prevention-not-enforced

google_storage_bucket.logs does not enforce GCS Public Access Prevention. Public principals can still be introduced through bucket IAM unless an organization-level policy blocks them.

Category
Information Disclosure
Boundary
internet-to-service:internet->google_storage_bucket.logs
Resources
google_storage_bucket.logs
Evidence
  • access control posture: public_access_prevention is unset
  • public exposure reasons: google_storage_bucket_iam_member.public_logs_reader grants roles/storage.objectViewer to allUsers

GCS bucket is publicly accessible

gcp-gcs-public-access

google_storage_bucket.logs is publicly reachable through GCS IAM grants. Public bucket access is a common source of unintended object disclosure.

Category
Information Disclosure
Boundary
internet-to-service:internet->google_storage_bucket.logs
Resources
google_storage_bucket.logs
Evidence
  • public exposure reasons: google_storage_bucket_iam_member.public_logs_reader grants roles/storage.objectViewer to allUsers

GCS sensitive bucket does not use customer-managed encryption

gcp-gcs-customer-managed-encryption-missing

google_storage_bucket.logs relies on default GCS encryption rather than a customer-managed KMS key. Sensitive buckets lose key ownership, rotation, and separation-of-duties controls that a CMEK can provide.

Category
Information Disclosure
Boundary
not-applicable
Resources
google_storage_bucket.logs
Evidence
  • encryption posture: default_kms_key_name is unset; customer_managed_encryption is false

GCS sensitive bucket retention policy is insufficient

gcp-gcs-retention-policy-insufficient

google_storage_bucket.logs does not have deterministic GCS retention posture that meets the minimum retention threshold and lock expectation. Retention policy and retention lock reduce destructive deletion or overwrite risk, but are distinct from soft-delete recovery controls.

Category
Denial of Service
Boundary
not-applicable
Resources
google_storage_bucket.logs
Evidence
  • retention policy issues: retention_policy is missing
  • retention policy posture: retention_policy.retention_period_state=missing; minimum_retention_period_days=7; minimum_retention_period_seconds=604800; retention_policy.is_locked is unset

GCS sensitive bucket versioning is disabled

gcp-gcs-versioning-disabled

google_storage_bucket.logs stores sensitive GCS data without bucket versioning. Accidental overwrites, deletes, or destructive changes have fewer object-level recovery options.

Category
Denial of Service
Boundary
not-applicable
Resources
google_storage_bucket.logs
Evidence
  • data protection posture: versioning.enabled is false; data_sensitivity is sensitive

GKE cluster does not enable Workload Identity

gcp-gke-workload-identity-disabled

google_container_cluster.app does not enable GKE Workload Identity. Pods are more likely to depend on node service-account credentials, which weakens workload-level identity boundaries and can expand blast radius after pod compromise.

Category
Elevation of Privilege
Boundary
not-applicable
Resources
google_container_cluster.app
Evidence
  • workload identity posture: workload_identity_enabled is false; workload_pool is unset

GKE cluster exposes a public control plane

gcp-gke-public-control-plane

google_container_cluster.app exposes a public GKE control-plane endpoint. Public API server reachability increases dependence on IAM, Kubernetes RBAC, and authorized network configuration to protect cluster administration.

Category
Spoofing
Boundary
internet-to-service:internet->google_container_cluster.app
Resources
google_container_cluster.app
Evidence
  • control plane endpoint: 35.4.5.6
  • public access reasons: GKE control plane endpoint is public
  • public exposure reasons: authorized network `anywhere` allows 0.0.0.0/0

GKE control plane allows broad authorized networks

gcp-gke-broad-authorized-networks

google_container_cluster.app exposes the GKE control plane without narrow master authorized networks. Internet-wide or unset CIDR controls leave the Kubernetes API server reachable from untrusted client networks.

Category
Spoofing
Boundary
internet-to-service:internet->google_container_cluster.app
Resources
google_container_cluster.app
Evidence
  • authorized networks: anywhere (0.0.0.0/0)
  • configured authorized network count: 1
  • public exposure reasons: authorized network `anywhere` allows 0.0.0.0/0

GKE control-plane logging is incomplete

gcp-gke-control-plane-logging-incomplete

google_container_cluster.app does not show deterministic GKE control-plane logging for key security components. Missing API server, scheduler, or controller manager logs can limit investigation of administrative and cluster-control activity.

Category
Repudiation
Boundary
not-applicable
Resources
google_container_cluster.app
Evidence
  • logging posture: control_plane_logging_state=not_configured; logging_service is not represented in planned values; logging_components are not represented in planned values; control-plane logging is not_configured

GKE network policy is not enabled

gcp-gke-network-policy-disabled

google_container_cluster.app does not deterministically enable GKE network policy. Without a pod network policy provider, Kubernetes workloads have weaker pod-level traffic isolation and lateral-movement controls.

Category
Tampering
Boundary
not-applicable
Resources
google_container_cluster.app
Evidence
  • network policy posture: network_policy_state=not_configured; network_policy_provider is not represented in planned values

GKE node metadata exposure is not hardened

gcp-gke-legacy-metadata-endpoints-enabled

google_container_node_pool.app allows legacy or broad node metadata exposure. Workloads on the node may be able to reach metadata credentials outside the intended GKE metadata server controls.

Category
Elevation of Privilege
Boundary
not-applicable
Resources
google_container_node_pool.app
Evidence
  • node metadata posture: legacy metadata endpoints are enabled; metadata mode is GCE_METADATA

GKE secrets encryption is not configured

gcp-gke-secrets-encryption-not-configured

google_container_cluster.app does not show deterministic GKE application-layer secrets encryption with a Cloud KMS key. Kubernetes secrets may not have customer-controlled encryption key ownership represented in the Terraform plan.

Category
Information Disclosure
Boundary
not-applicable
Resources
google_container_cluster.app
Evidence
  • secret encryption posture: secrets_encryption_state=disabled; database_encryption_state is not represented in planned values; database_encryption_key_name is not represented in planned values

Internet-exposed GCP compute instance permits broad ingress

gcp-public-compute-broad-ingress

google_compute_instance.web has an external access config and matching GCP firewall rules allow administrative access or all ports from the public internet. That broad ingress raises the chance of unauthenticated probing and credential attacks.

Category
Spoofing
Boundary
internet-to-service:internet->google_compute_instance.web
Resources
google_compute_instance.web, google_compute_firewall.public_admin
Evidence
  • firewall rules: google_compute_firewall.public_admin ingress tcp 22 from 0.0.0.0/0; google_compute_firewall.public_admin ingress tcp 3389 from 0.0.0.0/0
  • network tags: web
  • internet ingress reasons: google_compute_firewall.public_admin ingress tcp 22 from 0.0.0.0/0; google_compute_firewall.public_admin ingress tcp 3389 from 0.0.0.0/0; google_compute_firewall.public_all ingress tcp unspecified ports from 0.0.0.0/0
  • public exposure reasons: compute instance has an external access config and matching firewall rules allow internet ingress

Pub/Sub subscription does not configure a dead-letter policy

gcp-pubsub-subscription-dead-letter-policy-missing

google_pubsub_subscription.events does not configure a Pub/Sub dead-letter policy. Poison messages or repeated delivery failures can consume subscriber capacity and reduce recovery options for failed processing.

Category
Denial of Service
Boundary
not-applicable
Resources
google_pubsub_subscription.events
Evidence
  • target resource: address=google_pubsub_subscription.events; resource_type=google_pubsub_subscription
  • dead letter posture: dead_letter_policy_state=not_configured; dead_letter_topic=unset

Pub/Sub topic does not use customer-managed encryption

gcp-pubsub-topic-customer-managed-encryption-missing

google_pubsub_topic.events relies on Google-managed Pub/Sub encryption rather than a customer-managed Cloud KMS key. Google-managed encryption still protects message data; this finding concerns key ownership, rotation, audit separation, and compliance posture.

Category
Information Disclosure
Boundary
not-applicable
Resources
google_pubsub_topic.events
Evidence
  • target resource: address=google_pubsub_topic.events; resource_type=google_pubsub_topic
  • encryption ownership: cmek_state=not_configured; kms_key_name=unset

Secret Manager lifecycle posture is incomplete

gcp-secret-manager-lifecycle-posture-incomplete

google_secret_manager_secret.api_key does not show deterministic Secret Manager lifecycle posture for secret expiry or delayed version destruction. Expiry and version-destroy TTL controls reduce the lifetime of stale or accidentally destroyed secret material, but do not replace access review or rotation.

Category
Denial of Service
Boundary
not-applicable
Resources
google_secret_manager_secret.api_key
Evidence
  • target resource: address=google_secret_manager_secret.api_key; type=google_secret_manager_secret; identifier=projects/tfstride-demo/secrets/tfstride-api-key
  • lifecycle issues: secret has no ttl, expire_time, or version_destroy_ttl lifecycle guardrail; version_destroy_ttl is missing
  • lifecycle posture: ttl=unset; expire_time=unset; version_destroy_ttl=unset; minimum_version_destroy_ttl_days=7; minimum_version_destroy_ttl_seconds=604800

Secret Manager secret does not use customer-managed encryption

gcp-secret-manager-customer-managed-encryption-missing

google_secret_manager_secret.api_key relies on Google-managed Secret Manager encryption rather than a customer-managed Cloud KMS key. Google-managed encryption still applies; this finding concerns customer key ownership, rotation, audit separation, and compliance posture for sensitive secrets.

Category
Information Disclosure
Boundary
not-applicable
Resources
google_secret_manager_secret.api_key
Evidence
  • target resource: address=google_secret_manager_secret.api_key; type=google_secret_manager_secret; identifier=projects/tfstride-demo/secrets/tfstride-api-key
  • encryption ownership: customer_managed_encryption is false; secret_manager_replication_mode=automatic; secret_manager_kms_key_names is empty
  • replication posture: replication.mode=automatic

Sensitive GCP resource IAM binding allows broad or external access

gcp-sensitive-resource-iam-external-access

google_kms_crypto_key.customer grants `roles/cloudkms.cryptoKeyDecrypter` to `serviceAccount:decryptor@partner-project.iam.gserviceaccount.com` through GCP IAM. Public, broad-domain, or foreign-project principals can access sensitive secrets or cryptographic key operations outside the expected project trust boundary.

Category
Information Disclosure
Boundary
not-applicable
Resources
google_kms_crypto_key.customer, google_kms_crypto_key_iam_member.partner_decrypter
Evidence
  • iam binding: source=google_kms_crypto_key_iam_member.partner_decrypter; role=roles/cloudkms.cryptoKeyDecrypter; member=serviceAccount:decryptor@partner-project.iam.gserviceaccount.com
  • trust scope: service account belongs to project `partner-project`, outside resource project `tfstride-demo`
  • resource policy sources: google_kms_crypto_key_iam_member.partner_decrypter

Low

2

GKE Shielded Nodes is not enabled

gcp-gke-shielded-nodes-disabled-or-unknown

google_container_cluster.app does not show GKE Shielded Nodes enabled. Shielded Nodes add node integrity protections that reduce the impact of boot-level tampering and host compromise paths.

Category
Tampering
Boundary
not-applicable
Resources
google_container_cluster.app
Evidence
  • shielded nodes posture: shielded_nodes_state=unknown; shielded nodes setting is not represented in planned values

GKE legacy ABAC is enabled or unknown

gcp-gke-legacy-abac-enabled-or-unknown

google_container_cluster.app does not show legacy ABAC disabled. Legacy ABAC can bypass stronger IAM and Kubernetes RBAC expectations, and an unknown Terraform value should be reviewed before relying on RBAC-only authorization.

Category
Elevation of Privilege
Boundary
not-applicable
Resources
google_container_cluster.app
Evidence
  • legacy abac posture: legacy_abac_state=unknown; enable_legacy_abac is not represented in planned values

Observations

Controls and mitigating signals

No observations were recorded for this plan.

Trust boundaries

Crossings that drive the model

internet-to-service

internet -> google_cloud_run_v2_service.api

The resource is directly reachable or intentionally exposed to unauthenticated network clients.

internet-to-service

internet -> google_cloudfunctions_function.worker

The resource is directly reachable or intentionally exposed to unauthenticated network clients.

internet-to-service

internet -> google_compute_instance.web

The resource is directly reachable or intentionally exposed to unauthenticated network clients.

internet-to-service

internet -> google_container_cluster.app

The resource is directly reachable or intentionally exposed to unauthenticated network clients.

internet-to-service

internet -> google_sql_database_instance.app

The resource is directly reachable or intentionally exposed to unauthenticated network clients.

internet-to-service

internet -> google_storage_bucket.logs

The resource is directly reachable or intentionally exposed to unauthenticated network clients.

workload-to-data-store

google_cloud_run_v2_service.api -> google_sql_database_instance.app

Application or function workloads cross into a higher-sensitivity data plane when a directly internet-reachable database is reachable from a workload subnet with general egress.

workload-to-data-store

google_cloudfunctions_function.worker -> google_sql_database_instance.app

Application or function workloads cross into a higher-sensitivity data plane when a directly internet-reachable database is reachable from a workload subnet with general egress.

workload-to-data-store

google_compute_instance.web -> google_bigquery_dataset.analytics

GCP workloads cross into a higher-sensitivity data plane when their attached service account is granted data access through IAM: google_bigquery_dataset_iam_binding.analytics_viewers grants roles/bigquery.dataViewer to serviceAccount:tfstride-web@example.iam.gserviceaccount.com.

Raw outputs

Stable contract and markdown

JSON report
{
  "kind": "tfstride-report",
  "version": "1.1",
  "tool": {
    "name": "tfstride",
    "version": "0.4.23"
  },
  "title": "GCP Nightmare Plan Demo",
  "analyzed_file": "sample_gcp_nightmare_plan.json",
  "analyzed_path": "sample_gcp_nightmare_plan.json",
  "summary": {
    "normalized_resources": 31,
    "unsupported_resources": 0,
    "trust_boundaries": 9,
    "active_findings": 45,
    "total_findings": 45,
    "suppressed_findings": 0,
    "baselined_findings": 0,
    "severity_counts": {
      "high": 14,
      "medium": 29,
      "low": 2
    }
  },
  "filtering": {
    "total_findings": 45,
    "active_findings": 45,
    "suppressed_findings": 0,
    "baselined_findings": 0,
    "suppressions_path": null,
    "baseline_path": null
  },
  "analysis_coverage": {
    "resources": {
      "total_resources": 31,
      "provider_resources": 31,
      "normalized_resources": 31,
      "unsupported_resources": 0,
      "unsupported_resource_types": {}
    },
    "rules": {
      "registered_rule_count": 78,
      "enabled_rules": [
        "gcp-sensitive-resource-iam-external-access",
        "gcp-pubsub-public-access",
        "gcp-pubsub-topic-customer-managed-encryption-missing",
        "gcp-pubsub-message-retention-insufficient",
        "gcp-pubsub-subscription-dead-letter-policy-missing",
        "gcp-bigquery-public-access",
        "gcp-cloud-sql-public-authorized-network",
        "gcp-cloud-sql-backup-disabled",
        "gcp-cloud-sql-public-ip-without-private-network",
        "gcp-cloud-sql-ssl-not-required",
        "gcp-cloud-sql-point-in-time-recovery-disabled",
        "gcp-cloud-sql-deletion-protection-disabled",
        "gcp-cloud-sql-zonal-availability",
        "gcp-cloud-sql-query-insights-disabled",
        "gcp-cloud-sql-connector-enforcement-not-required",
        "gcp-cloud-sql-private-connectivity-not-modeled",
        "gcp-private-workload-private-google-access-disabled",
        "gcp-gcs-public-access",
        "gcp-gcs-uniform-bucket-level-access-disabled",
        "gcp-gcs-public-access-prevention-not-enforced",
        "gcp-gcs-versioning-disabled",
        "gcp-gcs-customer-managed-encryption-missing",
        "gcp-gcs-retention-policy-insufficient",
        "gcp-artifact-registry-docker-tags-mutable",
        "gcp-artifact-registry-customer-managed-encryption-missing",
        "gcp-artifact-registry-vulnerability-scanning-disabled",
        "gcp-secret-manager-customer-managed-encryption-missing",
        "gcp-secret-manager-lifecycle-posture-incomplete",
        "gcp-kms-key-rotation-not-configured-or-too-long",
        "gcp-kms-key-destroy-scheduled-duration-too-short",
        "gcp-public-compute-broad-ingress",
        "gcp-public-load-balanced-workload",
        "gcp-load-balancer-http-public-proxy",
        "gcp-load-balancer-ssl-policy-missing-or-weak",
        "gcp-public-load-balancer-cloud-armor-missing",
        "gcp-compute-os-login-disabled",
        "gcp-gke-public-control-plane",
        "gcp-gke-broad-authorized-networks",
        "gcp-gke-workload-identity-disabled",
        "gcp-gke-legacy-metadata-endpoints-enabled",
        "gcp-gke-broad-node-service-account",
        "gcp-gke-control-plane-logging-incomplete",
        "gcp-scc-asset-discovery-disabled",
        "gcp-logging-exclusion-drops-audit-security-logs",
        "gcp-logging-sink-audit-export-incomplete",
        "gcp-central-audit-sink-not-modeled",
        "gcp-subnetwork-flow-logs-not-configured",
        "gcp-subnetwork-flow-log-capture-incomplete",
        "gcp-gke-network-policy-disabled",
        "gcp-gke-secrets-encryption-not-configured",
        "gcp-gke-legacy-abac-enabled-or-unknown",
        "gcp-gke-client-certificate-auth-enabled-or-unknown",
        "gcp-gke-shielded-nodes-disabled-or-unknown",
        "gcp-gke-binary-authorization-not-enabled",
        "gcp-cloud-run-public-invoker",
        "gcp-cloud-functions-public-invoker",
        "gcp-cloud-run-image-not-digest-pinned",
        "gcp-cloud-run-artifact-registry-mutable-tag",
        "gcp-cloud-run-can-modify-image-repository",
        "gcp-cloud-run-sensitive-environment-value-inline",
        "gcp-cloud-run-secret-access-blast-radius",
        "gcp-public-cloud-run-gcs-mutation-access",
        "gcp-public-cloud-run-pubsub-mutation-access",
        "gcp-service-account-iam-broad-principal",
        "gcp-service-account-iam-privileged-role",
        "gcp-service-account-key-hygiene",
        "gcp-service-account-key-effective-access",
        "gcp-workload-identity-pool-wide-impersonation",
        "gcp-workload-identity-provider-unconditioned-broad-trust",
        "gcp-workload-identity-privileged-service-account-access",
        "gcp-org-folder-iam-broad-principal",
        "gcp-org-folder-iam-privileged-role",
        "gcp-project-iam-broad-principal",
        "gcp-project-iam-privileged-role",
        "gcp-iam-privileged-assignment",
        "gcp-inherited-iam-sensitive-resource-access",
        "gcp-inherited-iam-blast-radius",
        "gcp-public-workload-sensitive-data-access"
      ],
      "disabled_rules": [],
      "severity_overrides": {},
      "finding_counts_by_rule": {
        "gcp-sensitive-resource-iam-external-access": 2,
        "gcp-pubsub-public-access": 1,
        "gcp-pubsub-topic-customer-managed-encryption-missing": 1,
        "gcp-pubsub-message-retention-insufficient": 0,
        "gcp-pubsub-subscription-dead-letter-policy-missing": 1,
        "gcp-bigquery-public-access": 1,
        "gcp-cloud-sql-public-authorized-network": 1,
        "gcp-cloud-sql-backup-disabled": 1,
        "gcp-cloud-sql-public-ip-without-private-network": 1,
        "gcp-cloud-sql-ssl-not-required": 1,
        "gcp-cloud-sql-point-in-time-recovery-disabled": 0,
        "gcp-cloud-sql-deletion-protection-disabled": 1,
        "gcp-cloud-sql-zonal-availability": 1,
        "gcp-cloud-sql-query-insights-disabled": 0,
        "gcp-cloud-sql-connector-enforcement-not-required": 0,
        "gcp-cloud-sql-private-connectivity-not-modeled": 0,
        "gcp-private-workload-private-google-access-disabled": 0,
        "gcp-gcs-public-access": 1,
        "gcp-gcs-uniform-bucket-level-access-disabled": 0,
        "gcp-gcs-public-access-prevention-not-enforced": 1,
        "gcp-gcs-versioning-disabled": 1,
        "gcp-gcs-customer-managed-encryption-missing": 1,
        "gcp-gcs-retention-policy-insufficient": 1,
        "gcp-artifact-registry-docker-tags-mutable": 0,
        "gcp-artifact-registry-customer-managed-encryption-missing": 0,
        "gcp-artifact-registry-vulnerability-scanning-disabled": 0,
        "gcp-secret-manager-customer-managed-encryption-missing": 1,
        "gcp-secret-manager-lifecycle-posture-incomplete": 1,
        "gcp-kms-key-rotation-not-configured-or-too-long": 0,
        "gcp-kms-key-destroy-scheduled-duration-too-short": 0,
        "gcp-public-compute-broad-ingress": 1,
        "gcp-public-load-balanced-workload": 0,
        "gcp-load-balancer-http-public-proxy": 0,
        "gcp-load-balancer-ssl-policy-missing-or-weak": 0,
        "gcp-public-load-balancer-cloud-armor-missing": 0,
        "gcp-compute-os-login-disabled": 1,
        "gcp-gke-public-control-plane": 1,
        "gcp-gke-broad-authorized-networks": 1,
        "gcp-gke-workload-identity-disabled": 1,
        "gcp-gke-legacy-metadata-endpoints-enabled": 1,
        "gcp-gke-broad-node-service-account": 1,
        "gcp-gke-control-plane-logging-incomplete": 1,
        "gcp-scc-asset-discovery-disabled": 0,
        "gcp-logging-exclusion-drops-audit-security-logs": 0,
        "gcp-logging-sink-audit-export-incomplete": 0,
        "gcp-central-audit-sink-not-modeled": 0,
        "gcp-subnetwork-flow-logs-not-configured": 1,
        "gcp-subnetwork-flow-log-capture-incomplete": 0,
        "gcp-gke-network-policy-disabled": 1,
        "gcp-gke-secrets-encryption-not-configured": 1,
        "gcp-gke-legacy-abac-enabled-or-unknown": 1,
        "gcp-gke-client-certificate-auth-enabled-or-unknown": 0,
        "gcp-gke-shielded-nodes-disabled-or-unknown": 1,
        "gcp-gke-binary-authorization-not-enabled": 0,
        "gcp-cloud-run-public-invoker": 1,
        "gcp-cloud-functions-public-invoker": 1,
        "gcp-cloud-run-image-not-digest-pinned": 0,
        "gcp-cloud-run-artifact-registry-mutable-tag": 0,
        "gcp-cloud-run-can-modify-image-repository": 0,
        "gcp-cloud-run-sensitive-environment-value-inline": 0,
        "gcp-cloud-run-secret-access-blast-radius": 0,
        "gcp-public-cloud-run-gcs-mutation-access": 0,
        "gcp-public-cloud-run-pubsub-mutation-access": 0,
        "gcp-service-account-iam-broad-principal": 0,
        "gcp-service-account-iam-privileged-role": 0,
        "gcp-service-account-key-hygiene": 1,
        "gcp-service-account-key-effective-access": 1,
        "gcp-workload-identity-pool-wide-impersonation": 0,
        "gcp-workload-identity-provider-unconditioned-broad-trust": 0,
        "gcp-workload-identity-privileged-service-account-access": 0,
        "gcp-org-folder-iam-broad-principal": 1,
        "gcp-org-folder-iam-privileged-role": 1,
        "gcp-project-iam-broad-principal": 1,
        "gcp-project-iam-privileged-role": 1,
        "gcp-iam-privileged-assignment": 0,
        "gcp-inherited-iam-sensitive-resource-access": 1,
        "gcp-inherited-iam-blast-radius": 1,
        "gcp-public-workload-sensitive-data-access": 3
      }
    },
    "references": {
      "unresolved_reference_count": 0,
      "unresolved_references": []
    }
  },
  "inventory": {
    "provider": "gcp",
    "unsupported_resources": [],
    "metadata": {
      "supported_resource_types": [
        "google_artifact_registry_repository",
        "google_artifact_registry_repository_iam_binding",
        "google_artifact_registry_repository_iam_member",
        "google_artifact_registry_repository_iam_policy",
        "google_bigquery_dataset",
        "google_bigquery_dataset_iam_binding",
        "google_bigquery_dataset_iam_member",
        "google_bigquery_dataset_iam_policy",
        "google_bigquery_table",
        "google_bigquery_table_iam_binding",
        "google_bigquery_table_iam_member",
        "google_bigquery_table_iam_policy",
        "google_cloud_run_service",
        "google_cloud_run_service_iam_binding",
        "google_cloud_run_service_iam_member",
        "google_cloud_run_service_iam_policy",
        "google_cloud_run_v2_service",
        "google_cloud_run_v2_service_iam_binding",
        "google_cloud_run_v2_service_iam_member",
        "google_cloud_run_v2_service_iam_policy",
        "google_cloudfunctions2_function",
        "google_cloudfunctions2_function_iam_binding",
        "google_cloudfunctions2_function_iam_member",
        "google_cloudfunctions2_function_iam_policy",
        "google_cloudfunctions_function",
        "google_cloudfunctions_function_iam_binding",
        "google_cloudfunctions_function_iam_member",
        "google_cloudfunctions_function_iam_policy",
        "google_compute_backend_bucket",
        "google_compute_backend_service",
        "google_compute_firewall",
        "google_compute_firewall_policy",
        "google_compute_firewall_policy_association",
        "google_compute_firewall_policy_rule",
        "google_compute_forwarding_rule",
        "google_compute_global_address",
        "google_compute_global_forwarding_rule",
        "google_compute_instance",
        "google_compute_managed_ssl_certificate",
        "google_compute_network",
        "google_compute_network_endpoint_group",
        "google_compute_region_backend_service",
        "google_compute_region_network_endpoint_group",
        "google_compute_region_security_policy",
        "google_compute_region_target_http_proxy",
        "google_compute_region_target_https_proxy",
        "google_compute_region_url_map",
        "google_compute_route",
        "google_compute_router",
        "google_compute_router_nat",
        "google_compute_security_policy",
        "google_compute_service_attachment",
        "google_compute_ssl_policy",
        "google_compute_subnetwork",
        "google_compute_target_http_proxy",
        "google_compute_target_https_proxy",
        "google_compute_url_map",
        "google_container_cluster",
        "google_container_node_pool",
        "google_folder_iam_binding",
        "google_folder_iam_member",
        "google_folder_iam_policy",
        "google_folder_organization_policy",
        "google_iam_workload_identity_pool",
        "google_iam_workload_identity_pool_provider",
        "google_kms_crypto_key",
        "google_kms_crypto_key_iam_binding",
        "google_kms_crypto_key_iam_member",
        "google_kms_crypto_key_iam_policy",
        "google_kms_key_ring_iam_binding",
        "google_kms_key_ring_iam_member",
        "google_kms_key_ring_iam_policy",
        "google_logging_organization_exclusion",
        "google_logging_organization_sink",
        "google_logging_project_exclusion",
        "google_logging_project_sink",
        "google_network_connectivity_service_connection_policy",
        "google_org_policy_policy",
        "google_organization_iam_binding",
        "google_organization_iam_custom_role",
        "google_organization_iam_member",
        "google_organization_iam_policy",
        "google_organization_policy",
        "google_project_iam_binding",
        "google_project_iam_custom_role",
        "google_project_iam_member",
        "google_project_iam_policy",
        "google_project_organization_policy",
        "google_pubsub_subscription",
        "google_pubsub_subscription_iam_binding",
        "google_pubsub_subscription_iam_member",
        "google_pubsub_subscription_iam_policy",
        "google_pubsub_topic",
        "google_pubsub_topic_iam_binding",
        "google_pubsub_topic_iam_member",
        "google_pubsub_topic_iam_policy",
        "google_scc_organization_settings",
        "google_secret_manager_secret",
        "google_secret_manager_secret_iam_binding",
        "google_secret_manager_secret_iam_member",
        "google_secret_manager_secret_iam_policy",
        "google_service_account",
        "google_service_account_iam_binding",
        "google_service_account_iam_member",
        "google_service_account_iam_policy",
        "google_service_account_key",
        "google_service_networking_connection",
        "google_sql_database_instance",
        "google_storage_bucket",
        "google_storage_bucket_iam_binding",
        "google_storage_bucket_iam_member",
        "google_storage_bucket_iam_policy"
      ],
      "total_input_resources": 31,
      "provider_resource_count": 31,
      "normalized_resource_count": 31,
      "unsupported_resource_types": {}
    },
    "resources": [
      {
        "address": "google_bigquery_dataset.analytics",
        "provider": "gcp",
        "resource_type": "google_bigquery_dataset",
        "name": "analytics",
        "category": "data",
        "identifier": "projects/tfstride-demo/datasets/tfstride_analytics",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "sensitive",
        "metadata": {
          "name": "projects/tfstride-demo/datasets/tfstride_analytics",
          "project": "tfstride-demo",
          "bigquery_dataset_id": "tfstride_analytics",
          "bigquery_dataset_reference": "projects/tfstride-demo/datasets/tfstride_analytics",
          "labels": {
            "app": "tfstride"
          },
          "delete_contents_on_destroy": false,
          "default_table_expiration_ms": null,
          "description": null,
          "friendly_name": null,
          "location": "US",
          "max_time_travel_hours": null,
          "storage_billing_model": null,
          "customer_managed_encryption": false,
          "storage_encrypted": true,
          "iam_bindings": [
            {
              "role": "roles/bigquery.dataViewer",
              "members": [
                "allUsers",
                "serviceAccount:tfstride-web@example.iam.gserviceaccount.com"
              ],
              "source": "google_bigquery_dataset_iam_binding.analytics_viewers"
            }
          ],
          "gcp_resource_policy_source_addresses": [
            "google_bigquery_dataset_iam_binding.analytics_viewers"
          ]
        }
      },
      {
        "address": "google_bigquery_dataset_iam_binding.analytics_viewers",
        "provider": "gcp",
        "resource_type": "google_bigquery_dataset_iam_binding",
        "name": "analytics_viewers",
        "category": "iam",
        "identifier": "google_bigquery_dataset.analytics.dataset_id:roles/bigquery.dataViewer:allUsers,serviceAccount:tfstride-web@example.iam.gserviceaccount.com",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "bigquery_dataset_reference": "google_bigquery_dataset.analytics.dataset_id",
          "iam_role": "roles/bigquery.dataViewer",
          "iam_members": [
            "allUsers",
            "serviceAccount:tfstride-web@example.iam.gserviceaccount.com"
          ],
          "iam_condition": {},
          "iam_bindings": [
            {
              "role": "roles/bigquery.dataViewer",
              "members": [
                "allUsers",
                "serviceAccount:tfstride-web@example.iam.gserviceaccount.com"
              ]
            }
          ],
          "privileged_access_grants": []
        }
      },
      {
        "address": "google_bigquery_table.events",
        "provider": "gcp",
        "resource_type": "google_bigquery_table",
        "name": "events",
        "category": "data",
        "identifier": "projects/tfstride-demo/datasets/google_bigquery_dataset.analytics.dataset_id/tables/events",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "sensitive",
        "metadata": {
          "name": "projects/tfstride-demo/datasets/google_bigquery_dataset.analytics.dataset_id/tables/events",
          "project": "tfstride-demo",
          "bigquery_dataset_id": "google_bigquery_dataset.analytics.dataset_id",
          "bigquery_dataset_reference": "google_bigquery_dataset.analytics.dataset_id",
          "bigquery_table_id": "events",
          "bigquery_table_reference": "projects/tfstride-demo/datasets/google_bigquery_dataset.analytics.dataset_id/tables/events",
          "labels": {},
          "clustering": [],
          "deletion_protection": true,
          "description": null,
          "friendly_name": null,
          "schema": null,
          "time_partitioning": [],
          "view": [],
          "customer_managed_encryption": false,
          "storage_encrypted": true
        }
      },
      {
        "address": "google_cloud_run_v2_service.api",
        "provider": "gcp",
        "resource_type": "google_cloud_run_v2_service",
        "name": "api",
        "category": "compute",
        "identifier": "tfstride-api",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": true,
        "public_exposure": true,
        "data_sensitivity": "standard",
        "metadata": {
          "name": "tfstride-api",
          "project": "tfstride-demo",
          "service_account_email": "tfstride-run@tfstride-demo.iam.gserviceaccount.com",
          "service_account_member": "serviceAccount:tfstride-run@tfstride-demo.iam.gserviceaccount.com",
          "service_accounts": [
            {
              "email": "tfstride-run@tfstride-demo.iam.gserviceaccount.com"
            }
          ],
          "labels": {},
          "vpc_enabled": false,
          "provider_managed_egress": true,
          "cloud_run_service_reference": "tfstride-api",
          "region": "us-central1",
          "serverless_ingress": "INGRESS_TRAFFIC_ALL",
          "uri": "https://tfstride-api.run.app",
          "container_image_references": [],
          "container_image_posture_uncertainties": [],
          "cloud_run_secret_references": [],
          "cloud_run_secret_posture_uncertainties": [],
          "public_access_reasons": [
            "google_cloud_run_v2_service_iam_member.public_invoker grants roles/run.invoker to allUsers"
          ],
          "direct_internet_reachable": true,
          "public_exposure_reasons": [
            "google_cloud_run_v2_service_iam_member.public_invoker grants roles/run.invoker to allUsers"
          ],
          "iam_bindings": [
            {
              "role": "roles/run.invoker",
              "members": [
                "allUsers"
              ],
              "source": "google_cloud_run_v2_service_iam_member.public_invoker"
            }
          ],
          "gcp_resource_policy_source_addresses": [
            "google_cloud_run_v2_service_iam_member.public_invoker"
          ],
          "cloud_run_gcs_access_paths": [],
          "cloud_run_pubsub_access_paths": [],
          "cloud_run_secret_access_paths": [],
          "artifact_registry_write_paths": []
        }
      },
      {
        "address": "google_cloud_run_v2_service_iam_member.public_invoker",
        "provider": "gcp",
        "resource_type": "google_cloud_run_v2_service_iam_member",
        "name": "public_invoker",
        "category": "iam",
        "identifier": "tfstride-api:roles/run.invoker:allUsers",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "cloud_run_service_reference": "tfstride-api",
          "region": "us-central1",
          "iam_role": "roles/run.invoker",
          "iam_member": "allUsers",
          "iam_members": [
            "allUsers"
          ],
          "iam_condition": {},
          "iam_bindings": [
            {
              "role": "roles/run.invoker",
              "members": [
                "allUsers"
              ]
            }
          ],
          "privileged_access_grants": []
        }
      },
      {
        "address": "google_cloudfunctions_function.worker",
        "provider": "gcp",
        "resource_type": "google_cloudfunctions_function",
        "name": "worker",
        "category": "compute",
        "identifier": "tfstride-worker",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": true,
        "public_exposure": true,
        "data_sensitivity": "standard",
        "metadata": {
          "name": "tfstride-worker",
          "project": "tfstride-demo",
          "service_account_email": "tfstride-fn@tfstride-demo.iam.gserviceaccount.com",
          "service_account_member": "serviceAccount:tfstride-fn@tfstride-demo.iam.gserviceaccount.com",
          "service_accounts": [
            {
              "email": "tfstride-fn@tfstride-demo.iam.gserviceaccount.com"
            }
          ],
          "labels": {},
          "vpc_enabled": false,
          "provider_managed_egress": true,
          "cloud_function_reference": "tfstride-worker",
          "region": "us-central1",
          "runtime": "python312",
          "trigger_http": true,
          "https_trigger_url": null,
          "public_access_reasons": [
            "google_cloudfunctions_function_iam_member.public_invoker grants roles/cloudfunctions.invoker to allAuthenticatedUsers"
          ],
          "direct_internet_reachable": true,
          "public_exposure_reasons": [
            "google_cloudfunctions_function_iam_member.public_invoker grants roles/cloudfunctions.invoker to allAuthenticatedUsers"
          ],
          "iam_bindings": [
            {
              "role": "roles/cloudfunctions.invoker",
              "members": [
                "allAuthenticatedUsers"
              ],
              "source": "google_cloudfunctions_function_iam_member.public_invoker"
            }
          ],
          "gcp_resource_policy_source_addresses": [
            "google_cloudfunctions_function_iam_member.public_invoker"
          ]
        }
      },
      {
        "address": "google_cloudfunctions_function_iam_member.public_invoker",
        "provider": "gcp",
        "resource_type": "google_cloudfunctions_function_iam_member",
        "name": "public_invoker",
        "category": "iam",
        "identifier": "tfstride-worker:roles/cloudfunctions.invoker:allAuthenticatedUsers",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "cloud_function_reference": "tfstride-worker",
          "region": "us-central1",
          "iam_role": "roles/cloudfunctions.invoker",
          "iam_member": "allAuthenticatedUsers",
          "iam_members": [
            "allAuthenticatedUsers"
          ],
          "iam_condition": {},
          "iam_bindings": [
            {
              "role": "roles/cloudfunctions.invoker",
              "members": [
                "allAuthenticatedUsers"
              ]
            }
          ],
          "privileged_access_grants": []
        }
      },
      {
        "address": "google_compute_firewall.public_admin",
        "provider": "gcp",
        "resource_type": "google_compute_firewall",
        "name": "public_admin",
        "category": "network",
        "identifier": "tfstride-public-admin",
        "arn": null,
        "vpc_id": "google_compute_network.main.name",
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [
          {
            "direction": "ingress",
            "protocol": "tcp",
            "from_port": 22,
            "to_port": 22,
            "cidr_blocks": [
              "0.0.0.0/0"
            ],
            "ipv6_cidr_blocks": [],
            "referenced_security_group_ids": [],
            "description": null
          },
          {
            "direction": "ingress",
            "protocol": "tcp",
            "from_port": 3389,
            "to_port": 3389,
            "cidr_blocks": [
              "0.0.0.0/0"
            ],
            "ipv6_cidr_blocks": [],
            "referenced_security_group_ids": [],
            "description": null
          }
        ],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "name": "tfstride-public-admin",
          "project": "tfstride-demo",
          "network": "google_compute_network.main.name",
          "allow": [
            {
              "protocol": "tcp",
              "ports": [
                "22",
                "3389"
              ]
            }
          ],
          "deny": [],
          "source_ranges": [
            "0.0.0.0/0"
          ],
          "destination_ranges": [],
          "target_tags": [
            "web"
          ],
          "source_tags": [],
          "target_service_accounts": [],
          "source_service_accounts": [],
          "firewall_direction": "ingress",
          "firewall_disabled": false
        }
      },
      {
        "address": "google_compute_firewall.public_all",
        "provider": "gcp",
        "resource_type": "google_compute_firewall",
        "name": "public_all",
        "category": "network",
        "identifier": "tfstride-public-all",
        "arn": null,
        "vpc_id": "google_compute_network.main.name",
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [
          {
            "direction": "ingress",
            "protocol": "tcp",
            "from_port": null,
            "to_port": null,
            "cidr_blocks": [
              "0.0.0.0/0"
            ],
            "ipv6_cidr_blocks": [],
            "referenced_security_group_ids": [],
            "description": null
          }
        ],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "name": "tfstride-public-all",
          "project": "tfstride-demo",
          "network": "google_compute_network.main.name",
          "allow": [
            {
              "protocol": "tcp",
              "ports": []
            }
          ],
          "deny": [],
          "source_ranges": [
            "0.0.0.0/0"
          ],
          "destination_ranges": [],
          "target_tags": [
            "web"
          ],
          "source_tags": [],
          "target_service_accounts": [],
          "source_service_accounts": [],
          "firewall_direction": "ingress",
          "firewall_disabled": false
        }
      },
      {
        "address": "google_compute_instance.web",
        "provider": "gcp",
        "resource_type": "google_compute_instance",
        "name": "web",
        "category": "compute",
        "identifier": "tfstride-web",
        "arn": null,
        "vpc_id": "google_compute_network.main.id",
        "subnet_ids": [
          "google_compute_subnetwork.app.id"
        ],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": true,
        "public_exposure": true,
        "data_sensitivity": "standard",
        "metadata": {
          "name": "tfstride-web",
          "project": "tfstride-demo",
          "zone": "us-central1-a",
          "machine_type": "e2-medium",
          "network_tags": [
            "web"
          ],
          "network_interfaces": [
            {
              "subnetwork": "google_compute_subnetwork.app.id",
              "access_config": [
                {
                  "nat_ip": "35.1.2.3"
                }
              ]
            }
          ],
          "service_accounts": [
            {
              "email": "tfstride-web@example.iam.gserviceaccount.com",
              "scopes": [
                "cloud-platform"
              ]
            }
          ],
          "labels": {},
          "metadata": {
            "enable-oslogin": "false"
          },
          "can_ip_forward": false,
          "os_login_enabled": false,
          "public_access_reasons": [
            "compute instance has an external access config"
          ],
          "in_public_subnet": false,
          "has_nat_gateway_egress": false,
          "has_public_route": true,
          "internet_ingress_capable": true,
          "internet_ingress_reasons": [
            "google_compute_firewall.public_admin ingress tcp 22 from 0.0.0.0/0",
            "google_compute_firewall.public_admin ingress tcp 3389 from 0.0.0.0/0",
            "google_compute_firewall.public_all ingress tcp unspecified ports from 0.0.0.0/0"
          ],
          "internet_ingress_firewalls": [
            "google_compute_firewall.public_admin",
            "google_compute_firewall.public_all"
          ],
          "direct_internet_reachable": true,
          "public_exposure_reasons": [
            "compute instance has an external access config and matching firewall rules allow internet ingress"
          ]
        }
      },
      {
        "address": "google_compute_network.main",
        "provider": "gcp",
        "resource_type": "google_compute_network",
        "name": "main",
        "category": "network",
        "identifier": "tfstride-main",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "name": "tfstride-main",
          "project": "tfstride-demo",
          "auto_create_subnetworks": false,
          "routing_mode": "REGIONAL",
          "description": null
        }
      },
      {
        "address": "google_compute_route.default_internet",
        "provider": "gcp",
        "resource_type": "google_compute_route",
        "name": "default_internet",
        "category": "network",
        "identifier": "tfstride-default-internet",
        "arn": null,
        "vpc_id": "google_compute_network.main.id",
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "name": "tfstride-default-internet",
          "project": "tfstride-demo",
          "network": "google_compute_network.main.id",
          "route_dest_range": "0.0.0.0/0",
          "route_next_hop_gateway": "default-internet-gateway",
          "route_tags": [
            "web"
          ],
          "route_priority": 1000,
          "description": null
        }
      },
      {
        "address": "google_compute_subnetwork.app",
        "provider": "gcp",
        "resource_type": "google_compute_subnetwork",
        "name": "app",
        "category": "network",
        "identifier": "tfstride-app",
        "arn": null,
        "vpc_id": "google_compute_network.main.id",
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "name": "tfstride-app",
          "project": "tfstride-demo",
          "region": "us-central1",
          "network": "google_compute_network.main.id",
          "cidr_range": "10.10.1.0/24",
          "private_ip_google_access": true,
          "purpose": null,
          "stack_type": null,
          "secondary_ip_ranges": [],
          "subnetwork_flow_log_state": "not_configured",
          "subnetwork_flow_log_config": {},
          "subnetwork_flow_log_metadata_fields": [],
          "network_telemetry_posture_uncertainties": [],
          "has_public_route": false,
          "is_public_subnet": false,
          "has_nat_gateway_egress": false
        }
      },
      {
        "address": "google_container_cluster.app",
        "provider": "gcp",
        "resource_type": "google_container_cluster",
        "name": "app",
        "category": "compute",
        "identifier": "tfstride-gke",
        "arn": null,
        "vpc_id": "google_compute_network.main.id",
        "subnet_ids": [
          "google_compute_subnetwork.app.id"
        ],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": true,
        "public_exposure": true,
        "data_sensitivity": "standard",
        "metadata": {
          "name": "tfstride-gke",
          "project": "tfstride-demo",
          "region": "us-central1",
          "network": "google_compute_network.main.id",
          "subnetwork": "google_compute_subnetwork.app.id",
          "labels": {},
          "gke_node_oauth_scopes": [],
          "node_config": {},
          "node_metadata": {},
          "gke_endpoint": "35.4.5.6",
          "gke_private_endpoint_enabled": false,
          "gke_private_nodes_enabled": false,
          "gke_master_authorized_networks": [
            {
              "display_name": "anywhere",
              "cidr_block": "0.0.0.0/0"
            }
          ],
          "gke_workload_identity_enabled": false,
          "gke_logging_components": [],
          "gke_control_plane_logging_state": "not_configured",
          "gke_network_policy_state": "not_configured",
          "gke_secrets_encryption_state": "disabled",
          "gke_legacy_abac_state": "unknown",
          "gke_client_certificate_auth_state": "unknown",
          "gke_basic_auth_state": "unknown",
          "gke_shielded_nodes_state": "unknown",
          "gke_binary_authorization_state": "unknown",
          "private_cluster_config": {
            "enable_private_endpoint": false,
            "enable_private_nodes": false
          },
          "master_authorized_networks_config": {
            "cidr_blocks": [
              {
                "display_name": "anywhere",
                "cidr_block": "0.0.0.0/0"
              }
            ]
          },
          "workload_identity_config": {},
          "remove_default_node_pool": true,
          "public_access_reasons": [
            "GKE control plane endpoint is public"
          ],
          "direct_internet_reachable": true,
          "internet_ingress_capable": true,
          "internet_ingress_reasons": [
            "authorized network `anywhere` allows 0.0.0.0/0"
          ],
          "public_exposure_reasons": [
            "authorized network `anywhere` allows 0.0.0.0/0"
          ]
        }
      },
      {
        "address": "google_container_node_pool.app",
        "provider": "gcp",
        "resource_type": "google_container_node_pool",
        "name": "app",
        "category": "compute",
        "identifier": "tfstride-gke-app",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "name": "tfstride-gke-app",
          "project": "tfstride-demo",
          "region": "us-central1",
          "labels": {},
          "gke_node_service_account": "123456789-compute@developer.gserviceaccount.com",
          "gke_node_oauth_scopes": [
            "https://www.googleapis.com/auth/cloud-platform"
          ],
          "gke_node_metadata_mode": "GCE_METADATA",
          "gke_legacy_metadata_endpoints_enabled": true,
          "node_config": {
            "service_account": "123456789-compute@developer.gserviceaccount.com",
            "oauth_scopes": [
              "https://www.googleapis.com/auth/cloud-platform"
            ],
            "metadata": {
              "disable-legacy-endpoints": "false"
            },
            "workload_metadata_config": [
              {
                "mode": "GCE_METADATA"
              }
            ]
          },
          "node_metadata": {
            "disable-legacy-endpoints": "false"
          },
          "cluster": "google_container_cluster.app.name",
          "node_locations": [],
          "initial_node_count": null
        }
      },
      {
        "address": "google_folder_iam_member.folder_admin",
        "provider": "gcp",
        "resource_type": "google_folder_iam_member",
        "name": "folder_admin",
        "category": "iam",
        "identifier": "folders/12345:roles/resourcemanager.folderAdmin:group:folder-admins@example.com",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "folder_id": "folders/12345",
          "iam_role": "roles/resourcemanager.folderAdmin",
          "iam_member": "group:folder-admins@example.com",
          "iam_members": [
            "group:folder-admins@example.com"
          ],
          "iam_condition": {},
          "iam_bindings": [
            {
              "role": "roles/resourcemanager.folderAdmin",
              "members": [
                "group:folder-admins@example.com"
              ]
            }
          ],
          "privileged_access_grants": [
            {
              "provider": "gcp",
              "principal_type": "group",
              "principal_identifier": "group:folder-admins@example.com",
              "principal_display_name": "group:folder-admins@example.com",
              "principal_source_address": "google_folder_iam_member.folder_admin",
              "scope_kind": "folder",
              "scope_value": "folders/12345",
              "scope_source_address": null,
              "privilege_categories": [
                "iam-admin",
                "compute-admin"
              ],
              "confidence": "high",
              "assignment_source_address": "google_folder_iam_member.folder_admin",
              "role_name": "roles/resourcemanager.folderAdmin",
              "role_id": "roles/resourcemanager.folderAdmin",
              "permission_patterns": [
                "roles/resourcemanager.folderAdmin"
              ],
              "evidence": [
                "source=google_folder_iam_member.folder_admin",
                "role=roles/resourcemanager.folderAdmin",
                "member=group:folder-admins@example.com",
                "scope_kind=folder",
                "scope_value=folders/12345"
              ],
              "uncertainties": []
            }
          ]
        }
      },
      {
        "address": "google_kms_crypto_key.customer",
        "provider": "gcp",
        "resource_type": "google_kms_crypto_key",
        "name": "customer",
        "category": "data",
        "identifier": "projects/tfstride-demo/locations/global/keyRings/tfstride-app/cryptoKeys/tfstride-customer-key",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "sensitive",
        "metadata": {
          "name": "tfstride-customer-key",
          "project": "tfstride-demo",
          "kms_crypto_key_reference": "projects/tfstride-demo/locations/global/keyRings/tfstride-app/cryptoKeys/tfstride-customer-key",
          "kms_key_ring": "projects/tfstride-demo/locations/global/keyRings/tfstride-app",
          "kms_purpose": "ENCRYPT_DECRYPT",
          "kms_rotation_period": "7776000s",
          "kms_posture_uncertainties": [],
          "labels": {
            "app": "tfstride"
          },
          "import_only": false,
          "skip_initial_version_creation": false,
          "storage_encrypted": true,
          "iam_bindings": [
            {
              "role": "roles/cloudkms.cryptoKeyDecrypter",
              "members": [
                "serviceAccount:decryptor@partner-project.iam.gserviceaccount.com"
              ],
              "source": "google_kms_crypto_key_iam_member.partner_decrypter"
            }
          ],
          "gcp_resource_policy_source_addresses": [
            "google_kms_crypto_key_iam_member.partner_decrypter"
          ]
        }
      },
      {
        "address": "google_kms_crypto_key_iam_member.partner_decrypter",
        "provider": "gcp",
        "resource_type": "google_kms_crypto_key_iam_member",
        "name": "partner_decrypter",
        "category": "iam",
        "identifier": "google_kms_crypto_key.customer.id:roles/cloudkms.cryptoKeyDecrypter:serviceAccount:decryptor@partner-project.iam.gserviceaccount.com",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "kms_crypto_key_reference": "google_kms_crypto_key.customer.id",
          "iam_role": "roles/cloudkms.cryptoKeyDecrypter",
          "iam_member": "serviceAccount:decryptor@partner-project.iam.gserviceaccount.com",
          "iam_members": [
            "serviceAccount:decryptor@partner-project.iam.gserviceaccount.com"
          ],
          "iam_condition": {},
          "iam_bindings": [
            {
              "role": "roles/cloudkms.cryptoKeyDecrypter",
              "members": [
                "serviceAccount:decryptor@partner-project.iam.gserviceaccount.com"
              ]
            }
          ],
          "privileged_access_grants": []
        }
      },
      {
        "address": "google_logging_project_sink.processor",
        "provider": "gcp",
        "resource_type": "google_logging_project_sink",
        "name": "processor",
        "category": "iam",
        "identifier": "processor-logs",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "project": "tfstride-demo",
          "name": "processor-logs",
          "logging_sink_name": "processor-logs",
          "logging_sink_destination": "storage.googleapis.com/tfstride-logs",
          "logging_sink_scope_type": "project",
          "logging_sink_scope": "tfstride-demo",
          "audit_security_posture_uncertainties": []
        }
      },
      {
        "address": "google_organization_iam_binding.domain_viewer",
        "provider": "gcp",
        "resource_type": "google_organization_iam_binding",
        "name": "domain_viewer",
        "category": "iam",
        "identifier": "1234567890:roles/viewer:domain:example.com",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "organization_id": "1234567890",
          "iam_role": "roles/viewer",
          "iam_members": [
            "domain:example.com"
          ],
          "iam_condition": {},
          "iam_bindings": [
            {
              "role": "roles/viewer",
              "members": [
                "domain:example.com"
              ]
            }
          ],
          "privileged_access_grants": []
        }
      },
      {
        "address": "google_project_iam_member.public_owner",
        "provider": "gcp",
        "resource_type": "google_project_iam_member",
        "name": "public_owner",
        "category": "iam",
        "identifier": "roles/owner:allUsers",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "project": "tfstride-demo",
          "iam_role": "roles/owner",
          "iam_member": "allUsers",
          "iam_members": [
            "allUsers"
          ],
          "iam_condition": {},
          "iam_bindings": [
            {
              "role": "roles/owner",
              "members": [
                "allUsers"
              ]
            }
          ],
          "privileged_access_grants": [
            {
              "provider": "gcp",
              "principal_type": "any-principal",
              "principal_identifier": "allUsers",
              "principal_display_name": "allUsers",
              "principal_source_address": "google_project_iam_member.public_owner",
              "scope_kind": "project",
              "scope_value": "tfstride-demo",
              "scope_source_address": null,
              "privilege_categories": [
                "full-admin",
                "iam-admin",
                "policy-admin"
              ],
              "confidence": "high",
              "assignment_source_address": "google_project_iam_member.public_owner",
              "role_name": "roles/owner",
              "role_id": "roles/owner",
              "permission_patterns": [
                "roles/owner"
              ],
              "evidence": [
                "source=google_project_iam_member.public_owner",
                "role=roles/owner",
                "member=allUsers",
                "scope_kind=project",
                "scope_value=tfstride-demo"
              ],
              "uncertainties": []
            }
          ]
        }
      },
      {
        "address": "google_pubsub_subscription.events",
        "provider": "gcp",
        "resource_type": "google_pubsub_subscription",
        "name": "events",
        "category": "data",
        "identifier": "tfstride-events-sub",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "sensitive",
        "metadata": {
          "name": "tfstride-events-sub",
          "project": "tfstride-demo",
          "pubsub_subscription_reference": "tfstride-events-sub",
          "pubsub_topic_reference": "google_pubsub_topic.events.id",
          "labels": {},
          "pubsub_subscription_ack_deadline_seconds": 20,
          "pubsub_subscription_dead_letter_policy": [],
          "pubsub_subscription_dead_letter_policy_state": "not_configured",
          "pubsub_subscription_expiration_policy": [],
          "pubsub_subscription_message_retention_state": "not_configured",
          "pubsub_subscription_push_config": [],
          "pubsub_subscription_retain_acked_messages": false,
          "pubsub_subscription_retry_policy": [],
          "pubsub_posture_uncertainties": [],
          "storage_encrypted": true
        }
      },
      {
        "address": "google_pubsub_topic.events",
        "provider": "gcp",
        "resource_type": "google_pubsub_topic",
        "name": "events",
        "category": "data",
        "identifier": "tfstride-events",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "sensitive",
        "metadata": {
          "name": "tfstride-events",
          "project": "tfstride-demo",
          "pubsub_topic_reference": "tfstride-events",
          "labels": {
            "app": "tfstride"
          },
          "pubsub_topic_cmek_state": "not_configured",
          "pubsub_topic_message_retention_state": "not_configured",
          "pubsub_topic_message_storage_policy": [],
          "pubsub_topic_schema_settings": [],
          "pubsub_posture_uncertainties": [],
          "customer_managed_encryption": false,
          "storage_encrypted": true,
          "iam_bindings": [
            {
              "role": "roles/pubsub.publisher",
              "members": [
                "allAuthenticatedUsers"
              ],
              "source": "google_pubsub_topic_iam_member.public_publisher"
            }
          ],
          "gcp_resource_policy_source_addresses": [
            "google_pubsub_topic_iam_member.public_publisher"
          ]
        }
      },
      {
        "address": "google_pubsub_topic_iam_member.public_publisher",
        "provider": "gcp",
        "resource_type": "google_pubsub_topic_iam_member",
        "name": "public_publisher",
        "category": "iam",
        "identifier": "google_pubsub_topic.events.name:roles/pubsub.publisher:allAuthenticatedUsers",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "pubsub_topic_reference": "google_pubsub_topic.events.name",
          "iam_role": "roles/pubsub.publisher",
          "iam_member": "allAuthenticatedUsers",
          "iam_members": [
            "allAuthenticatedUsers"
          ],
          "iam_condition": {},
          "iam_bindings": [
            {
              "role": "roles/pubsub.publisher",
              "members": [
                "allAuthenticatedUsers"
              ]
            }
          ],
          "privileged_access_grants": []
        }
      },
      {
        "address": "google_secret_manager_secret.api_key",
        "provider": "gcp",
        "resource_type": "google_secret_manager_secret",
        "name": "api_key",
        "category": "data",
        "identifier": "projects/tfstride-demo/secrets/tfstride-api-key",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "sensitive",
        "metadata": {
          "name": "projects/tfstride-demo/secrets/tfstride-api-key",
          "secret_id": "tfstride-api-key",
          "project": "tfstride-demo",
          "labels": {
            "app": "tfstride"
          },
          "secret_manager_replication_mode": "automatic",
          "secret_manager_kms_key_names": [],
          "secret_manager_replication": {
            "mode": "automatic"
          },
          "secret_manager_posture_uncertainties": [],
          "annotations": {},
          "topics": [],
          "customer_managed_encryption": false,
          "storage_encrypted": true,
          "iam_bindings": [
            {
              "role": "roles/secretmanager.secretAccessor",
              "members": [
                "allAuthenticatedUsers"
              ],
              "source": "google_secret_manager_secret_iam_member.public_accessor"
            }
          ],
          "gcp_resource_policy_source_addresses": [
            "google_secret_manager_secret_iam_member.public_accessor"
          ]
        }
      },
      {
        "address": "google_secret_manager_secret_iam_member.public_accessor",
        "provider": "gcp",
        "resource_type": "google_secret_manager_secret_iam_member",
        "name": "public_accessor",
        "category": "iam",
        "identifier": "google_secret_manager_secret.api_key.id:roles/secretmanager.secretAccessor:allAuthenticatedUsers",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "secret_reference": "google_secret_manager_secret.api_key.id",
          "project": "tfstride-demo",
          "iam_role": "roles/secretmanager.secretAccessor",
          "iam_member": "allAuthenticatedUsers",
          "iam_members": [
            "allAuthenticatedUsers"
          ],
          "iam_condition": {},
          "iam_bindings": [
            {
              "role": "roles/secretmanager.secretAccessor",
              "members": [
                "allAuthenticatedUsers"
              ]
            }
          ],
          "privileged_access_grants": []
        }
      },
      {
        "address": "google_service_account.web",
        "provider": "gcp",
        "resource_type": "google_service_account",
        "name": "web",
        "category": "iam",
        "identifier": "tfstride-web@example.iam.gserviceaccount.com",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "name": "projects/tfstride-demo/serviceAccounts/tfstride-web@example.iam.gserviceaccount.com",
          "project": "tfstride-demo",
          "service_account_account_id": "tfstride-web",
          "service_account_email": "tfstride-web@example.iam.gserviceaccount.com",
          "service_account_member": "serviceAccount:tfstride-web@example.iam.gserviceaccount.com",
          "service_account_unique_id": "100000000000000000001",
          "service_account_disabled": false,
          "display_name": "tfSTRIDE web workload",
          "description": "Service account used by the sample web workload."
        }
      },
      {
        "address": "google_service_account_key.web",
        "provider": "gcp",
        "resource_type": "google_service_account_key",
        "name": "web",
        "category": "iam",
        "identifier": "projects/tfstride-demo/serviceAccounts/tfstride-web@example.iam.gserviceaccount.com/keys/sample-key",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "name": "projects/tfstride-demo/serviceAccounts/tfstride-web@example.iam.gserviceaccount.com/keys/sample-key",
          "service_account_id": "google_service_account.web.email",
          "service_account_reference": "google_service_account.web.email",
          "service_account_key_algorithm": "KEY_ALG_RSA_2048",
          "service_account_public_key_type": "TYPE_X509_PEM_FILE",
          "valid_after": "2026-01-01T00:00:00Z",
          "valid_before": "2027-01-01T00:00:00Z",
          "keepers": {}
        }
      },
      {
        "address": "google_sql_database_instance.app",
        "provider": "gcp",
        "resource_type": "google_sql_database_instance",
        "name": "app",
        "category": "data",
        "identifier": "tfstride-app-db",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": true,
        "public_exposure": true,
        "data_sensitivity": "sensitive",
        "metadata": {
          "name": "tfstride-app-db",
          "project": "tfstride-demo",
          "region": "us-central1",
          "database_version": "POSTGRES_15",
          "availability_type": "ZONAL",
          "cloud_sql_query_insights_state": "not_configured",
          "cloud_sql_insights_config": {},
          "cloud_sql_deletion_protection_state": "unknown",
          "cloud_sql_posture_uncertainties": [],
          "cloud_sql_ipv4_enabled": true,
          "cloud_sql_backup_enabled": false,
          "cloud_sql_point_in_time_recovery_enabled": false,
          "cloud_sql_require_ssl": false,
          "cloud_sql_authorized_networks": [
            {
              "name": "anywhere",
              "value": "0.0.0.0/0"
            }
          ],
          "cloud_sql_backup_configuration": {
            "enabled": false,
            "point_in_time_recovery_enabled": false
          },
          "cloud_sql_ip_configuration": {
            "ipv4_enabled": true,
            "require_ssl": false,
            "authorized_networks": [
              {
                "name": "anywhere",
                "value": "0.0.0.0/0"
              }
            ]
          },
          "deletion_protection": false,
          "labels": {},
          "tier": "db-f1-micro",
          "disk_type": "PD_SSD",
          "disk_size": 20,
          "public_access_reasons": [
            "Cloud SQL public IPv4 access is enabled"
          ],
          "direct_internet_reachable": true,
          "internet_ingress_capable": true,
          "internet_ingress_reasons": [
            "authorized network `anywhere` allows 0.0.0.0/0"
          ],
          "public_exposure_reasons": [
            "authorized network `anywhere` allows 0.0.0.0/0"
          ],
          "publicly_accessible": true,
          "storage_encrypted": true
        }
      },
      {
        "address": "google_storage_bucket.logs",
        "provider": "gcp",
        "resource_type": "google_storage_bucket",
        "name": "logs",
        "category": "data",
        "identifier": "tfstride-logs",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": true,
        "public_exposure": true,
        "data_sensitivity": "sensitive",
        "metadata": {
          "name": "tfstride-logs",
          "bucket": "tfstride-logs",
          "project": "tfstride-demo",
          "labels": {},
          "uniform_bucket_level_access": true,
          "gcs_versioning_enabled": false,
          "gcs_versioning_configuration": {},
          "gcs_encryption_configuration": {},
          "gcs_retention_policy_configuration": {},
          "gcs_retention_policy_uncertainties": [],
          "location": "US",
          "storage_class": null,
          "force_destroy": false,
          "customer_managed_encryption": false,
          "storage_encrypted": true,
          "public_access_reasons": [
            "google_storage_bucket_iam_member.public_logs_reader grants roles/storage.objectViewer to allUsers"
          ],
          "direct_internet_reachable": true,
          "public_exposure_reasons": [
            "google_storage_bucket_iam_member.public_logs_reader grants roles/storage.objectViewer to allUsers"
          ],
          "iam_bindings": [
            {
              "role": "roles/storage.objectViewer",
              "members": [
                "allUsers"
              ],
              "source": "google_storage_bucket_iam_member.public_logs_reader"
            }
          ],
          "gcp_resource_policy_source_addresses": [
            "google_storage_bucket_iam_member.public_logs_reader"
          ]
        }
      },
      {
        "address": "google_storage_bucket_iam_member.public_logs_reader",
        "provider": "gcp",
        "resource_type": "google_storage_bucket_iam_member",
        "name": "public_logs_reader",
        "category": "iam",
        "identifier": "google_storage_bucket.logs.name:roles/storage.objectViewer:allUsers",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "bucket": "google_storage_bucket.logs.name",
          "iam_role": "roles/storage.objectViewer",
          "iam_member": "allUsers",
          "iam_members": [
            "allUsers"
          ],
          "iam_condition": {},
          "iam_bindings": [
            {
              "role": "roles/storage.objectViewer",
              "members": [
                "allUsers"
              ]
            }
          ],
          "privileged_access_grants": []
        }
      }
    ]
  },
  "trust_boundaries": [
    {
      "identifier": "internet-to-service:internet->google_cloud_run_v2_service.api",
      "boundary_type": "internet-to-service",
      "source": "internet",
      "target": "google_cloud_run_v2_service.api",
      "description": "Traffic can cross from the public internet to google_cloud_run_v2_service.api.",
      "rationale": "The resource is directly reachable or intentionally exposed to unauthenticated network clients."
    },
    {
      "identifier": "internet-to-service:internet->google_cloudfunctions_function.worker",
      "boundary_type": "internet-to-service",
      "source": "internet",
      "target": "google_cloudfunctions_function.worker",
      "description": "Traffic can cross from the public internet to google_cloudfunctions_function.worker.",
      "rationale": "The resource is directly reachable or intentionally exposed to unauthenticated network clients."
    },
    {
      "identifier": "internet-to-service:internet->google_compute_instance.web",
      "boundary_type": "internet-to-service",
      "source": "internet",
      "target": "google_compute_instance.web",
      "description": "Traffic can cross from the public internet to google_compute_instance.web.",
      "rationale": "The resource is directly reachable or intentionally exposed to unauthenticated network clients."
    },
    {
      "identifier": "internet-to-service:internet->google_container_cluster.app",
      "boundary_type": "internet-to-service",
      "source": "internet",
      "target": "google_container_cluster.app",
      "description": "Traffic can cross from the public internet to google_container_cluster.app.",
      "rationale": "The resource is directly reachable or intentionally exposed to unauthenticated network clients."
    },
    {
      "identifier": "internet-to-service:internet->google_sql_database_instance.app",
      "boundary_type": "internet-to-service",
      "source": "internet",
      "target": "google_sql_database_instance.app",
      "description": "Traffic can cross from the public internet to google_sql_database_instance.app.",
      "rationale": "The resource is directly reachable or intentionally exposed to unauthenticated network clients."
    },
    {
      "identifier": "internet-to-service:internet->google_storage_bucket.logs",
      "boundary_type": "internet-to-service",
      "source": "internet",
      "target": "google_storage_bucket.logs",
      "description": "Traffic can cross from the public internet to google_storage_bucket.logs.",
      "rationale": "The resource is directly reachable or intentionally exposed to unauthenticated network clients."
    },
    {
      "identifier": "workload-to-data-store:google_cloud_run_v2_service.api->google_sql_database_instance.app",
      "boundary_type": "workload-to-data-store",
      "source": "google_cloud_run_v2_service.api",
      "target": "google_sql_database_instance.app",
      "description": "google_cloud_run_v2_service.api can interact with google_sql_database_instance.app.",
      "rationale": "Application or function workloads cross into a higher-sensitivity data plane when a directly internet-reachable database is reachable from a workload subnet with general egress."
    },
    {
      "identifier": "workload-to-data-store:google_cloudfunctions_function.worker->google_sql_database_instance.app",
      "boundary_type": "workload-to-data-store",
      "source": "google_cloudfunctions_function.worker",
      "target": "google_sql_database_instance.app",
      "description": "google_cloudfunctions_function.worker can interact with google_sql_database_instance.app.",
      "rationale": "Application or function workloads cross into a higher-sensitivity data plane when a directly internet-reachable database is reachable from a workload subnet with general egress."
    },
    {
      "identifier": "workload-to-data-store:google_compute_instance.web->google_bigquery_dataset.analytics",
      "boundary_type": "workload-to-data-store",
      "source": "google_compute_instance.web",
      "target": "google_bigquery_dataset.analytics",
      "description": "google_compute_instance.web can interact with google_bigquery_dataset.analytics.",
      "rationale": "GCP workloads cross into a higher-sensitivity data plane when their attached service account is granted data access through IAM: google_bigquery_dataset_iam_binding.analytics_viewers grants roles/bigquery.dataViewer to serviceAccount:tfstride-web@example.iam.gserviceaccount.com."
    }
  ],
  "findings": [
    {
      "fingerprint": "sha256:8c74c28ba2223af9fe27d104c317aad0cf77b75e2f1ffe4b32615981e1a3786a",
      "title": "BigQuery IAM binding allows public or broad data access",
      "rule_id": "gcp-bigquery-public-access",
      "category": "Information Disclosure",
      "severity": "high",
      "affected_resources": [
        "google_bigquery_dataset.analytics",
        "google_bigquery_dataset_iam_binding.analytics_viewers"
      ],
      "trust_boundary_id": null,
      "rationale": "google_bigquery_dataset.analytics grants `roles/bigquery.dataViewer` to `allUsers` through BigQuery IAM. Public or broad principals can read or modify analytical data outside the expected project trust boundary.",
      "recommended_mitigation": "Grant BigQuery dataset and table access only to specific in-project identities or reviewed analytics groups, remove public principals, and prefer least-privilege data roles.",
      "evidence": [
        {
          "key": "iam_binding",
          "values": [
            "source=google_bigquery_dataset_iam_binding.analytics_viewers",
            "role=roles/bigquery.dataViewer",
            "member=allUsers"
          ]
        },
        {
          "key": "trust_scope",
          "values": [
            "member is public GCP principal `allUsers`"
          ]
        },
        {
          "key": "resource_policy_sources",
          "values": [
            "google_bigquery_dataset_iam_binding.analytics_viewers"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 2,
        "data_sensitivity": 2,
        "lateral_movement": 1,
        "blast_radius": 2,
        "final_score": 9,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:ea244fab8b597f86d6033e9dd1a7a85fcd2582156da247f7cf41dc56ce1996aa",
      "title": "Cloud SQL instance accepts public authorized network access",
      "rule_id": "gcp-cloud-sql-public-authorized-network",
      "category": "Information Disclosure",
      "severity": "high",
      "affected_resources": [
        "google_sql_database_instance.app"
      ],
      "trust_boundary_id": "internet-to-service:internet->google_sql_database_instance.app",
      "rationale": "google_sql_database_instance.app has a public Cloud SQL IPv4 endpoint and an authorized network that allows internet-wide client sources. That weakens the database trust boundary even when database authentication is still required.",
      "recommended_mitigation": "Disable public IPv4 access where possible, use private IP connectivity or the Cloud SQL Auth Proxy, and restrict authorized networks to narrow CIDRs when public client access is required.",
      "evidence": [
        {
          "key": "authorized_networks",
          "values": [
            "anywhere (0.0.0.0/0)"
          ]
        },
        {
          "key": "public_exposure_reasons",
          "values": [
            "authorized network `anywhere` allows 0.0.0.0/0"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 6,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:65fcde0f677cf2cb623f5613d5d1ce0b50a1ebcd04b751275fd39030fdf0df25",
      "title": "GCP organization or folder IAM grants a high-privilege role",
      "rule_id": "gcp-org-folder-iam-privileged-role",
      "category": "Elevation of Privilege",
      "severity": "high",
      "affected_resources": [
        "google_folder_iam_member.folder_admin"
      ],
      "trust_boundary_id": null,
      "rationale": "google_folder_iam_member.folder_admin grants the high-impact GCP role `roles/resourcemanager.folderAdmin` to `group:folder-admins@example.com` at folder scope `folders/12345`. That role enables folder hierarchy administration across a high-level resource boundary and can materially expand blast radius if the principal is compromised.",
      "recommended_mitigation": "Replace high-impact organization and folder roles with narrowly scoped custom or predefined roles, assign them only to controlled break-glass or platform groups, and review descendant project blast radius.",
      "evidence": [
        {
          "key": "iam_binding",
          "values": [
            "member=group:folder-admins@example.com",
            "role=roles/resourcemanager.folderAdmin"
          ]
        },
        {
          "key": "scope",
          "values": [
            "folder scope `folders/12345`"
          ]
        },
        {
          "key": "role_risk",
          "values": [
            "folder hierarchy administration"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 2,
        "data_sensitivity": 0,
        "lateral_movement": 2,
        "blast_radius": 2,
        "final_score": 6,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:db008d55197805c722b864c414ff495c9ef525a478ddfc690418863829564ab0",
      "title": "GCP organization or folder IAM grants access to broad principals",
      "rule_id": "gcp-org-folder-iam-broad-principal",
      "category": "Elevation of Privilege",
      "severity": "high",
      "affected_resources": [
        "google_organization_iam_binding.domain_viewer"
      ],
      "trust_boundary_id": null,
      "rationale": "google_organization_iam_binding.domain_viewer grants `roles/viewer` to `domain:example.com` at organization scope `1234567890`. Public or broad-domain principals at organization or folder scope can expand access across many descendant projects and workloads.",
      "recommended_mitigation": "Remove public and broad-domain principals from organization and folder IAM, grant high-level access only to tightly controlled groups, and prefer project- or resource-scoped bindings where possible.",
      "evidence": [
        {
          "key": "iam_binding",
          "values": [
            "member=domain:example.com",
            "role=roles/viewer"
          ]
        },
        {
          "key": "scope",
          "values": [
            "organization scope `1234567890`"
          ]
        },
        {
          "key": "trust_scope",
          "values": [
            "member grants a whole Google Workspace domain"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 2,
        "data_sensitivity": 0,
        "lateral_movement": 2,
        "blast_radius": 2,
        "final_score": 6,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:c0b0c9b2c2eb55aafcaad00abfe94cf525fef9b6b18a19c72b20fd1446e1f0f0",
      "title": "GCP project IAM binding grants a high-privilege role",
      "rule_id": "gcp-project-iam-privileged-role",
      "category": "Elevation of Privilege",
      "severity": "high",
      "affected_resources": [
        "google_project_iam_member.public_owner"
      ],
      "trust_boundary_id": null,
      "rationale": "google_project_iam_member.public_owner grants the high-impact GCP role `roles/owner` to `allUsers` at project scope. That role enables full project administration and can materially expand control-plane blast radius if the principal is compromised or mis-scoped.",
      "recommended_mitigation": "Replace Owner, Editor, IAM admin, service-account impersonation, and admin-class project roles with narrowly scoped predefined or custom roles assigned to specific groups or service accounts.",
      "evidence": [
        {
          "key": "iam_binding",
          "values": [
            "member=allUsers",
            "role=roles/owner"
          ]
        },
        {
          "key": "role_risk",
          "values": [
            "full project administration"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 2,
        "data_sensitivity": 0,
        "lateral_movement": 2,
        "blast_radius": 2,
        "final_score": 6,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:28fb6117ee37f719c61424c06d297ce2a6a8c7a5a39fbbf562f344dd08716986",
      "title": "GCP service account key can exercise sensitive or privileged access",
      "rule_id": "gcp-service-account-key-effective-access",
      "category": "Elevation of Privilege",
      "severity": "high",
      "affected_resources": [
        "google_service_account.web",
        "google_service_account_key.web",
        "google_bigquery_dataset.analytics",
        "google_bigquery_dataset_iam_binding.analytics_viewers"
      ],
      "trust_boundary_id": null,
      "rationale": "google_service_account_key.web creates portable credentials for `google_service_account.web`, and that service account has sensitive data access or high-impact IAM grants. A copied key can exercise those effective permissions outside the intended workload boundary.",
      "recommended_mitigation": "Remove sensitive data and high-impact IAM grants from service accounts that still have user-managed keys, replace keys with workload identity or service-account impersonation, and revoke or rotate existing keys after privilege reduction.",
      "evidence": [
        {
          "key": "key_context",
          "values": [
            "source=google_service_account_key.web",
            "service_account_reference=google_service_account.web.email",
            "resolved_service_account=google_service_account.web"
          ]
        },
        {
          "key": "service_account_principals",
          "values": [
            "serviceAccount:tfstride-web@example.iam.gserviceaccount.com",
            "tfstride-web@example.iam.gserviceaccount.com"
          ]
        },
        {
          "key": "effective_access",
          "values": [
            "resource=google_bigquery_dataset.analytics; source=google_bigquery_dataset_iam_binding.analytics_viewers; scope=BigQuery dataset IAM; role=roles/bigquery.dataViewer; member=serviceAccount:tfstride-web@example.iam.gserviceaccount.com; risk=BigQuery dataset IAM grants roles/bigquery.dataViewer"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 1,
        "data_sensitivity": 2,
        "lateral_movement": 1,
        "blast_radius": 2,
        "final_score": 6,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:7dbdc36e5499aa747b7729f3d7cb25edb41dbcda72232f4f11aa978d5b00d668",
      "title": "GKE node pool uses broad node identity settings",
      "rule_id": "gcp-gke-broad-node-service-account",
      "category": "Elevation of Privilege",
      "severity": "high",
      "affected_resources": [
        "google_container_node_pool.app"
      ],
      "trust_boundary_id": null,
      "rationale": "google_container_node_pool.app uses broad GKE node identity settings. Default or broadly scoped node service accounts can turn a node or pod compromise into wider GCP API access.",
      "recommended_mitigation": "Attach a dedicated least-privilege node service account, remove cloud-platform or full-control OAuth scopes, and shift workload permissions to Workload Identity bindings.",
      "evidence": [
        {
          "key": "node_identity_risks",
          "values": [
            "node service account uses default Compute Engine identity `123456789-compute@developer.gserviceaccount.com`",
            "node OAuth scope is broad: https://www.googleapis.com/auth/cloud-platform"
          ]
        },
        {
          "key": "node_service_account",
          "values": [
            "123456789-compute@developer.gserviceaccount.com"
          ]
        },
        {
          "key": "oauth_scopes",
          "values": [
            "https://www.googleapis.com/auth/cloud-platform"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 2,
        "data_sensitivity": 0,
        "lateral_movement": 2,
        "blast_radius": 2,
        "final_score": 6,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:b5e1d4ef2d62e8e314ecd6a6e922a931592efd1c1ca6bfdf6b8b6d92134acf13",
      "title": "Inherited GCP IAM grant expands descendant blast radius",
      "rule_id": "gcp-inherited-iam-blast-radius",
      "category": "Elevation of Privilege",
      "severity": "high",
      "affected_resources": [
        "google_project_iam_member.public_owner",
        "google_bigquery_dataset.analytics",
        "google_bigquery_table.events",
        "google_cloud_run_v2_service.api",
        "google_cloudfunctions_function.worker",
        "google_compute_firewall.public_admin",
        "google_compute_firewall.public_all",
        "google_compute_instance.web",
        "google_compute_network.main",
        "google_compute_route.default_internet",
        "google_compute_subnetwork.app",
        "google_container_cluster.app",
        "google_container_node_pool.app",
        "google_kms_crypto_key.customer",
        "google_logging_project_sink.processor",
        "google_pubsub_subscription.events",
        "google_pubsub_topic.events",
        "google_secret_manager_secret.api_key",
        "google_service_account.web",
        "google_service_account_key.web",
        "google_sql_database_instance.app",
        "google_storage_bucket.logs"
      ],
      "trust_boundary_id": null,
      "rationale": "google_project_iam_member.public_owner grants `roles/owner` to `allUsers` at project scope `tfstride-demo`, and that inherited grant applies to 21 concrete descendant resource(s). A high-level IAM grant with broad, external, or high-impact access increases control-plane blast radius because compromise or misuse can affect resources below the inherited scope.",
      "recommended_mitigation": "Avoid broad or high-impact IAM grants at organization, folder, and project scope when narrower resource-level or workload-specific bindings are possible; split inherited roles by service and review descendant resources before assigning public, external, or administrator principals.",
      "evidence": [
        {
          "key": "iam_binding",
          "values": [
            "source=google_project_iam_member.public_owner",
            "scope=project:tfstride-demo",
            "member=allUsers",
            "role=roles/owner"
          ]
        },
        {
          "key": "role_risk",
          "values": [
            "full project administration"
          ]
        },
        {
          "key": "trust_scope",
          "values": [
            "member is public GCP principal `allUsers`"
          ]
        },
        {
          "key": "descendant_scope",
          "values": [
            "scope=project:tfstride-demo",
            "descendant_count=21",
            "resource_type_count=20",
            "projects=tfstride-demo"
          ]
        },
        {
          "key": "descendant_resource_types",
          "values": [
            "google_bigquery_dataset: 1",
            "google_bigquery_table: 1",
            "google_cloud_run_v2_service: 1",
            "google_cloudfunctions_function: 1",
            "google_compute_firewall: 2",
            "google_compute_instance: 1",
            "google_compute_network: 1",
            "google_compute_route: 1",
            "google_compute_subnetwork: 1",
            "google_container_cluster: 1",
            "google_container_node_pool: 1",
            "google_kms_crypto_key: 1",
            "google_logging_project_sink: 1",
            "google_pubsub_subscription: 1",
            "google_pubsub_topic: 1",
            "google_secret_manager_secret: 1",
            "google_service_account: 1",
            "google_service_account_key: 1",
            "google_sql_database_instance: 1",
            "google_storage_bucket: 1"
          ]
        },
        {
          "key": "descendant_resources",
          "values": [
            "google_bigquery_dataset.analytics",
            "google_bigquery_table.events",
            "google_cloud_run_v2_service.api",
            "google_cloudfunctions_function.worker",
            "google_compute_firewall.public_admin",
            "google_compute_firewall.public_all",
            "google_compute_instance.web",
            "google_compute_network.main",
            "google_compute_route.default_internet",
            "google_compute_subnetwork.app",
            "and 11 more descendant resources"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 2,
        "data_sensitivity": 2,
        "lateral_movement": 2,
        "blast_radius": 2,
        "final_score": 10,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:9b9e869d486c0af98acbef40bc8b49f84c8628cfd5821fa316a0549addb384f6",
      "title": "Inherited GCP IAM grant reaches sensitive resources",
      "rule_id": "gcp-inherited-iam-sensitive-resource-access",
      "category": "Information Disclosure",
      "severity": "high",
      "affected_resources": [
        "google_project_iam_member.public_owner",
        "google_bigquery_dataset.analytics",
        "google_bigquery_table.events",
        "google_kms_crypto_key.customer",
        "google_pubsub_subscription.events",
        "google_pubsub_topic.events",
        "google_secret_manager_secret.api_key",
        "google_sql_database_instance.app",
        "google_storage_bucket.logs"
      ],
      "trust_boundary_id": null,
      "rationale": "google_project_iam_member.public_owner grants `roles/owner` to `allUsers` at project scope `tfstride-demo`, and that inherited grant reaches 8 sensitive GCP descendant resource(s). Project, folder, and organization IAM applies below the grant scope, so a single ancestor binding can expose data resources beyond their local IAM boundary.",
      "recommended_mitigation": "Move sensitive data access off organization, folder, and project-level IAM where possible; grant Secret Manager, KMS, GCS, Cloud SQL, BigQuery, and Pub/Sub permissions at the narrowest resource scope with reviewed principals and custom roles.",
      "evidence": [
        {
          "key": "iam_binding",
          "values": [
            "source=google_project_iam_member.public_owner",
            "scope=project:tfstride-demo",
            "member=allUsers",
            "role=roles/owner"
          ]
        },
        {
          "key": "sensitive_descendants",
          "values": [
            "resource=google_bigquery_dataset.analytics; type=google_bigquery_dataset; risk=BigQuery dataset data access through roles/owner",
            "resource=google_bigquery_table.events; type=google_bigquery_table; risk=BigQuery table data access through roles/owner",
            "resource=google_kms_crypto_key.customer; type=google_kms_crypto_key; risk=Cloud KMS cryptographic key access through roles/owner",
            "resource=google_pubsub_subscription.events; type=google_pubsub_subscription; risk=Pub/Sub subscription data access through roles/owner",
            "resource=google_pubsub_topic.events; type=google_pubsub_topic; risk=Pub/Sub topic data access through roles/owner",
            "resource=google_secret_manager_secret.api_key; type=google_secret_manager_secret; risk=Secret Manager secret access through roles/owner",
            "resource=google_sql_database_instance.app; type=google_sql_database_instance; risk=Cloud SQL client/admin access through roles/owner",
            "resource=google_storage_bucket.logs; type=google_storage_bucket; risk=GCS object data access through roles/owner"
          ]
        },
        {
          "key": "trust_scope",
          "values": [
            "member is public GCP principal `allUsers`"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 2,
        "data_sensitivity": 2,
        "lateral_movement": 1,
        "blast_radius": 2,
        "final_score": 9,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:02d194ab06c27b5c48c7f8863730a4100d08d2224951b4a8aaf14fc7c611f023",
      "title": "Internet-exposed GCP workload can access sensitive data services",
      "rule_id": "gcp-public-workload-sensitive-data-access",
      "category": "Information Disclosure",
      "severity": "high",
      "affected_resources": [
        "google_cloud_run_v2_service.api",
        "google_sql_database_instance.app"
      ],
      "trust_boundary_id": "workload-to-data-store:google_cloud_run_v2_service.api->google_sql_database_instance.app",
      "rationale": "google_cloud_run_v2_service.api is internet-exposed and runs with GCP workload identity serviceAccount:tfstride-run@tfstride-demo.iam.gserviceaccount.com. That identity can access google_sql_database_instance.app. A compromise of the public workload can therefore become direct access to sensitive GCP data services.",
      "recommended_mitigation": "Run public GCP workloads with narrowly scoped service accounts, remove direct Secret Manager, Cloud KMS, GCS, or Cloud SQL grants from internet-facing instances, and broker sensitive data access through private services where possible.",
      "evidence": [
        {
          "key": "public_exposure_reasons",
          "values": [
            "google_cloud_run_v2_service_iam_member.public_invoker grants roles/run.invoker to allUsers"
          ]
        },
        {
          "key": "workload_identity",
          "values": [
            "serviceAccount:tfstride-run@tfstride-demo.iam.gserviceaccount.com"
          ]
        },
        {
          "key": "data_access_path",
          "values": [
            "google_cloud_run_v2_service.api reaches google_sql_database_instance.app"
          ]
        },
        {
          "key": "boundary_rationale",
          "values": [
            "Application or function workloads cross into a higher-sensitivity data plane when a directly internet-reachable database is reachable from a workload subnet with general egress."
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 1,
        "data_sensitivity": 2,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 7,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:302eadd78cb28178bcf10a5c2e647376e43e308cc8d0dcaf65adf5c06a924427",
      "title": "Internet-exposed GCP workload can access sensitive data services",
      "rule_id": "gcp-public-workload-sensitive-data-access",
      "category": "Information Disclosure",
      "severity": "high",
      "affected_resources": [
        "google_cloudfunctions_function.worker",
        "google_sql_database_instance.app"
      ],
      "trust_boundary_id": "workload-to-data-store:google_cloudfunctions_function.worker->google_sql_database_instance.app",
      "rationale": "google_cloudfunctions_function.worker is internet-exposed and runs with GCP workload identity serviceAccount:tfstride-fn@tfstride-demo.iam.gserviceaccount.com. That identity can access google_sql_database_instance.app. A compromise of the public workload can therefore become direct access to sensitive GCP data services.",
      "recommended_mitigation": "Run public GCP workloads with narrowly scoped service accounts, remove direct Secret Manager, Cloud KMS, GCS, or Cloud SQL grants from internet-facing instances, and broker sensitive data access through private services where possible.",
      "evidence": [
        {
          "key": "public_exposure_reasons",
          "values": [
            "google_cloudfunctions_function_iam_member.public_invoker grants roles/cloudfunctions.invoker to allAuthenticatedUsers"
          ]
        },
        {
          "key": "workload_identity",
          "values": [
            "serviceAccount:tfstride-fn@tfstride-demo.iam.gserviceaccount.com"
          ]
        },
        {
          "key": "data_access_path",
          "values": [
            "google_cloudfunctions_function.worker reaches google_sql_database_instance.app"
          ]
        },
        {
          "key": "boundary_rationale",
          "values": [
            "Application or function workloads cross into a higher-sensitivity data plane when a directly internet-reachable database is reachable from a workload subnet with general egress."
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 1,
        "data_sensitivity": 2,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 7,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:ef139b4e20dc1f10522b417424c5b7cc88a9063aee35b5f0b643f0329233c326",
      "title": "Internet-exposed GCP workload can access sensitive data services",
      "rule_id": "gcp-public-workload-sensitive-data-access",
      "category": "Information Disclosure",
      "severity": "high",
      "affected_resources": [
        "google_compute_instance.web",
        "google_bigquery_dataset.analytics",
        "google_bigquery_dataset_iam_binding.analytics_viewers"
      ],
      "trust_boundary_id": "workload-to-data-store:google_compute_instance.web->google_bigquery_dataset.analytics",
      "rationale": "google_compute_instance.web is internet-exposed and runs with GCP workload identity serviceAccount:tfstride-web@example.iam.gserviceaccount.com. That identity can access google_bigquery_dataset.analytics. A compromise of the public workload can therefore become direct access to sensitive GCP data services.",
      "recommended_mitigation": "Run public GCP workloads with narrowly scoped service accounts, remove direct Secret Manager, Cloud KMS, GCS, or Cloud SQL grants from internet-facing instances, and broker sensitive data access through private services where possible.",
      "evidence": [
        {
          "key": "public_exposure_reasons",
          "values": [
            "compute instance has an external access config and matching firewall rules allow internet ingress"
          ]
        },
        {
          "key": "workload_identity",
          "values": [
            "serviceAccount:tfstride-web@example.iam.gserviceaccount.com"
          ]
        },
        {
          "key": "workload_identity_scopes",
          "values": [
            "cloud-platform"
          ]
        },
        {
          "key": "data_access_path",
          "values": [
            "google_compute_instance.web reaches google_bigquery_dataset.analytics"
          ]
        },
        {
          "key": "boundary_rationale",
          "values": [
            "GCP workloads cross into a higher-sensitivity data plane when their attached service account is granted data access through IAM: google_bigquery_dataset_iam_binding.analytics_viewers grants roles/bigquery.dataViewer to serviceAccount:tfstride-web@example.iam.gserviceaccount.com."
          ]
        },
        {
          "key": "resource_policy_sources",
          "values": [
            "google_bigquery_dataset_iam_binding.analytics_viewers"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 1,
        "data_sensitivity": 2,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 7,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:86d087ae3581ec714df99490d6c8eea1073e5a3ff78d5d4b9c8cf877533e3448",
      "title": "Pub/Sub IAM binding allows public or broad data access",
      "rule_id": "gcp-pubsub-public-access",
      "category": "Information Disclosure",
      "severity": "high",
      "affected_resources": [
        "google_pubsub_topic.events",
        "google_pubsub_topic_iam_member.public_publisher"
      ],
      "trust_boundary_id": null,
      "rationale": "google_pubsub_topic.events grants `roles/pubsub.publisher` to `allAuthenticatedUsers` through Pub/Sub IAM. Public or broad principals can publish, consume, or administer event streams outside the expected service boundary.",
      "recommended_mitigation": "Grant Pub/Sub publisher and subscriber roles only to specific service accounts or groups, remove public principals, and separate publish and consume permissions by workload.",
      "evidence": [
        {
          "key": "iam_binding",
          "values": [
            "source=google_pubsub_topic_iam_member.public_publisher",
            "role=roles/pubsub.publisher",
            "member=allAuthenticatedUsers"
          ]
        },
        {
          "key": "trust_scope",
          "values": [
            "member is public GCP principal `allAuthenticatedUsers`"
          ]
        },
        {
          "key": "resource_policy_sources",
          "values": [
            "google_pubsub_topic_iam_member.public_publisher"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 2,
        "data_sensitivity": 1,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 7,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:dcda21548d88813aa36e2cf734e63769e0d32d5bcc6bb38b1f39ca442702b607",
      "title": "Sensitive GCP resource IAM binding allows broad or external access",
      "rule_id": "gcp-sensitive-resource-iam-external-access",
      "category": "Information Disclosure",
      "severity": "high",
      "affected_resources": [
        "google_secret_manager_secret.api_key",
        "google_secret_manager_secret_iam_member.public_accessor"
      ],
      "trust_boundary_id": null,
      "rationale": "google_secret_manager_secret.api_key grants `roles/secretmanager.secretAccessor` to `allAuthenticatedUsers` through GCP IAM. Public, broad-domain, or foreign-project principals can access sensitive secrets or cryptographic key operations outside the expected project trust boundary.",
      "recommended_mitigation": "Grant Secret Manager and Cloud KMS IAM roles only to specific in-project service accounts or groups, remove public principals, and require explicit cross-project access reviews for partner identities.",
      "evidence": [
        {
          "key": "iam_binding",
          "values": [
            "source=google_secret_manager_secret_iam_member.public_accessor",
            "role=roles/secretmanager.secretAccessor",
            "member=allAuthenticatedUsers"
          ]
        },
        {
          "key": "trust_scope",
          "values": [
            "member is public GCP principal `allAuthenticatedUsers`"
          ]
        },
        {
          "key": "resource_policy_sources",
          "values": [
            "google_secret_manager_secret_iam_member.public_accessor"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 2,
        "data_sensitivity": 2,
        "lateral_movement": 1,
        "blast_radius": 2,
        "final_score": 9,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:26d830ba0ec2a53756c3eaced1c3be81057169315b2b42d8c7419e083cfc77d6",
      "title": "Cloud Functions function is publicly invokable",
      "rule_id": "gcp-cloud-functions-public-invoker",
      "category": "Spoofing",
      "severity": "medium",
      "affected_resources": [
        "google_cloudfunctions_function.worker",
        "google_cloudfunctions_function_iam_member.public_invoker"
      ],
      "trust_boundary_id": "internet-to-service:internet->google_cloudfunctions_function.worker",
      "rationale": "google_cloudfunctions_function.worker allows public HTTP access and grants Cloud Functions invoke permission to public GCP principals. Unauthenticated internet clients can reach the function entry point without an organization-owned identity boundary.",
      "recommended_mitigation": "Remove `allUsers` and `allAuthenticatedUsers` from Cloud Functions invoker bindings unless anonymous access is intentional, and require authentication, IAP, API Gateway, or a controlled edge policy for public HTTP functions.",
      "evidence": [
        {
          "key": "public_invoker_bindings",
          "values": [
            "source=google_cloudfunctions_function_iam_member.public_invoker; role=roles/cloudfunctions.invoker; member=allAuthenticatedUsers"
          ]
        },
        {
          "key": "public_access_reasons",
          "values": [
            "google_cloudfunctions_function_iam_member.public_invoker grants roles/cloudfunctions.invoker to allAuthenticatedUsers"
          ]
        },
        {
          "key": "public_exposure_reasons",
          "values": [
            "google_cloudfunctions_function_iam_member.public_invoker grants roles/cloudfunctions.invoker to allAuthenticatedUsers"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 0,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:fdfa137966c89eb875eb160f45285149877d78495eec49c0a7250ae0a64e7a28",
      "title": "Cloud Run service is publicly invokable",
      "rule_id": "gcp-cloud-run-public-invoker",
      "category": "Spoofing",
      "severity": "medium",
      "affected_resources": [
        "google_cloud_run_v2_service.api",
        "google_cloud_run_v2_service_iam_member.public_invoker"
      ],
      "trust_boundary_id": "internet-to-service:internet->google_cloud_run_v2_service.api",
      "rationale": "google_cloud_run_v2_service.api allows public ingress and grants Cloud Run invoke permission to public GCP principals. Unauthenticated internet clients can reach the service entry point without an organization-owned identity boundary.",
      "recommended_mitigation": "Remove `allUsers` and `allAuthenticatedUsers` from Cloud Run invoker bindings unless anonymous access is intentional, and front public services with authentication, IAP, API Gateway, or a controlled edge policy.",
      "evidence": [
        {
          "key": "public_invoker_bindings",
          "values": [
            "source=google_cloud_run_v2_service_iam_member.public_invoker; role=roles/run.invoker; member=allUsers"
          ]
        },
        {
          "key": "public_access_reasons",
          "values": [
            "google_cloud_run_v2_service_iam_member.public_invoker grants roles/run.invoker to allUsers"
          ]
        },
        {
          "key": "public_exposure_reasons",
          "values": [
            "google_cloud_run_v2_service_iam_member.public_invoker grants roles/run.invoker to allUsers"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 0,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:732031ebf10c1377662fe780b23c0062f4bd35fca0ff1594e027473c04ad58b3",
      "title": "Cloud SQL automated backups are disabled",
      "rule_id": "gcp-cloud-sql-backup-disabled",
      "category": "Denial of Service",
      "severity": "medium",
      "affected_resources": [
        "google_sql_database_instance.app"
      ],
      "trust_boundary_id": null,
      "rationale": "google_sql_database_instance.app does not have Cloud SQL automated backups enabled. A destructive change, operator error, or data corruption event would have fewer managed recovery points.",
      "recommended_mitigation": "Enable automated backups for Cloud SQL instances, configure retention appropriate to the workload, and enable point-in-time recovery where supported.",
      "evidence": [
        {
          "key": "backup_posture",
          "values": [
            "backup_configuration.enabled is false",
            "point_in_time_recovery_enabled is false",
            "engine is POSTGRES_15"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:45d6257e521b0a506b22d24effc4ea056c44258268d8daf7718eb88fa7d08ee0",
      "title": "Cloud SQL deletion protection is disabled",
      "rule_id": "gcp-cloud-sql-deletion-protection-disabled",
      "category": "Denial of Service",
      "severity": "medium",
      "affected_resources": [
        "google_sql_database_instance.app"
      ],
      "trust_boundary_id": null,
      "rationale": "google_sql_database_instance.app has Cloud SQL deletion protection disabled. Accidental or unauthorized infrastructure changes could destroy the managed database instance without this provider-level guardrail.",
      "recommended_mitigation": "Enable Cloud SQL deletion protection for persistent environments and require explicit review before disabling it during planned database retirement.",
      "evidence": [
        {
          "key": "lifecycle_posture",
          "values": [
            "deletion_protection is false"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:a9a311adbcdee8161de2e4e8e8247dee5c199db0555e662a89c4626bb18a2a24",
      "title": "Cloud SQL instance uses zonal availability",
      "rule_id": "gcp-cloud-sql-zonal-availability",
      "category": "Denial of Service",
      "severity": "medium",
      "affected_resources": [
        "google_sql_database_instance.app"
      ],
      "trust_boundary_id": null,
      "rationale": "google_sql_database_instance.app uses zonal Cloud SQL availability. A zonal failure or maintenance disruption can leave the database unavailable longer than a regional high-availability deployment.",
      "recommended_mitigation": "Use `REGIONAL` availability for production Cloud SQL instances that require higher availability, then validate application failover behavior and recovery objectives.",
      "evidence": [
        {
          "key": "availability_posture",
          "values": [
            "availability_type=ZONAL",
            "engine=POSTGRES_15"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:6d18157ff1cecde179c5827e348e0ea19bcb17e4fb3d3ecf1a2394d940215cb6",
      "title": "Cloud SQL public IPv4 is enabled without private network access",
      "rule_id": "gcp-cloud-sql-public-ip-without-private-network",
      "category": "Information Disclosure",
      "severity": "medium",
      "affected_resources": [
        "google_sql_database_instance.app"
      ],
      "trust_boundary_id": "internet-to-service:internet->google_sql_database_instance.app",
      "rationale": "google_sql_database_instance.app has Cloud SQL public IPv4 enabled without a private network attachment. That keeps database client access on a public endpoint instead of an internal VPC path.",
      "recommended_mitigation": "Disable public IPv4 where possible, attach the instance to a private network, and route clients through private IP, the Cloud SQL Auth Proxy, or tightly controlled connectivity paths.",
      "evidence": [
        {
          "key": "network_posture",
          "values": [
            "ipv4_enabled is true",
            "private_network is unset",
            "authorized_networks configured: 1"
          ]
        },
        {
          "key": "public_access_reasons",
          "values": [
            "Cloud SQL public IPv4 access is enabled"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 1,
        "blast_radius": 0,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:2f9a3d374af8b51e6e3aa80ad9da2145f6f078927c72b74c19ab52f0d3266d8c",
      "title": "Cloud SQL public client access does not require SSL",
      "rule_id": "gcp-cloud-sql-ssl-not-required",
      "category": "Information Disclosure",
      "severity": "medium",
      "affected_resources": [
        "google_sql_database_instance.app"
      ],
      "trust_boundary_id": "internet-to-service:internet->google_sql_database_instance.app",
      "rationale": "google_sql_database_instance.app allows Cloud SQL public IPv4 client access without requiring encrypted client connections. Credentials and database traffic should not depend on client-side optional TLS behavior.",
      "recommended_mitigation": "Require encrypted Cloud SQL client connections with `require_ssl` or an enforcing `ssl_mode`, and prefer private IP or the Cloud SQL Auth Proxy for application connectivity.",
      "evidence": [
        {
          "key": "ssl_posture",
          "values": [
            "require_ssl is false",
            "ssl_mode is unset",
            "ipv4_enabled is true"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 1,
        "blast_radius": 0,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:cf045d82abf9eb22d59cbc03ddb4d9f079c49d771b3e395bf64dc215946993d6",
      "title": "GCP compute instance disables OS Login",
      "rule_id": "gcp-compute-os-login-disabled",
      "category": "Elevation of Privilege",
      "severity": "medium",
      "affected_resources": [
        "google_compute_instance.web"
      ],
      "trust_boundary_id": null,
      "rationale": "google_compute_instance.web explicitly disables OS Login. SSH access can therefore fall back to instance or project metadata keys instead of centralized IAM-backed login and audit controls.",
      "recommended_mitigation": "Enable OS Login on GCE instances and manage SSH access through IAM roles, two-factor enforcement, and centralized audit logs instead of metadata SSH keys.",
      "evidence": [
        {
          "key": "os_login_posture",
          "values": [
            "metadata.enable-oslogin is false"
          ]
        },
        {
          "key": "public_exposure_reasons",
          "values": [
            "compute instance has an external access config and matching firewall rules allow internet ingress"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 1,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:9e2b756e54082b4289f04abfd9f944579cd25a4175b15dffec45da14f8a7741e",
      "title": "GCP project IAM binding grants access to public principals",
      "rule_id": "gcp-project-iam-broad-principal",
      "category": "Elevation of Privilege",
      "severity": "medium",
      "affected_resources": [
        "google_project_iam_member.public_owner"
      ],
      "trust_boundary_id": null,
      "rationale": "google_project_iam_member.public_owner grants `roles/owner` to `allUsers` at project scope. Public or broadly authenticated principals can cross into the control plane without an organization-owned identity boundary.",
      "recommended_mitigation": "Remove `allUsers` and `allAuthenticatedUsers` from project-level IAM bindings, grant access to specific groups or service accounts, and scope permissions to the smallest project or resource needed.",
      "evidence": [
        {
          "key": "iam_binding",
          "values": [
            "member=allUsers",
            "role=roles/owner"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 1,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:556a241d54f7b6b0865f194d59c860efffbac01aaad254d687d6f439632fca8f",
      "title": "GCP service account user-managed key lacks rotation hygiene",
      "rule_id": "gcp-service-account-key-hygiene",
      "category": "Spoofing",
      "severity": "medium",
      "affected_resources": [
        "google_service_account.web",
        "google_service_account_key.web"
      ],
      "trust_boundary_id": null,
      "rationale": "google_service_account_key.web creates a user-managed GCP service account key for `google_service_account.web`. User-managed service account keys are portable, long-lived credentials that can be copied outside GCP control, so they need explicit rotation controls or should be replaced with workload identity or impersonation flows.",
      "recommended_mitigation": "Avoid user-managed service account keys where Workload Identity Federation, workload identity, or service-account impersonation can be used; when keys are unavoidable, keep lifetimes short, configure explicit rotation triggers, and store private material outside Terraform state.",
      "evidence": [
        {
          "key": "key_context",
          "values": [
            "source=google_service_account_key.web",
            "service_account_reference=google_service_account.web.email",
            "key_algorithm=KEY_ALG_RSA_2048",
            "public_key_type=TYPE_X509_PEM_FILE"
          ]
        },
        {
          "key": "key_risk",
          "values": [
            "Terraform manages a user-created service-account key",
            "validity window is 365 days and exceeds 180-day threshold",
            "no Terraform keepers rotation trigger observed"
          ]
        },
        {
          "key": "validity_window",
          "values": [
            "valid_after=2026-01-01T00:00:00Z",
            "valid_before=2027-01-01T00:00:00Z",
            "validity_days=365"
          ]
        },
        {
          "key": "rotation_control",
          "values": [
            "no Terraform keepers rotation trigger observed"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 1,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 2,
        "final_score": 4,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:d7380b4b3e19c2f29c68019a1757075b9455a4465c9cf613a0fd4a3a2d8dc9e9",
      "title": "GCP subnetwork Flow Logs are not configured",
      "rule_id": "gcp-subnetwork-flow-logs-not-configured",
      "category": "Repudiation",
      "severity": "medium",
      "affected_resources": [
        "google_compute_subnetwork.app"
      ],
      "trust_boundary_id": null,
      "rationale": "google_compute_subnetwork.app does not configure VPC Flow Logs in this Terraform plan. Without subnetwork flow telemetry, network investigation, lateral-movement review, and egress analysis can lack packet-flow evidence for workloads attached to this subnet.",
      "recommended_mitigation": "Enable VPC Flow Logs on subnetworks that host workloads, keep the flow log configuration in Terraform, and export or retain those logs according to investigation and monitoring requirements.",
      "evidence": [
        {
          "key": "subnetwork_flow_log_posture",
          "values": [
            "address=google_compute_subnetwork.app",
            "type=google_compute_subnetwork",
            "name=app",
            "identifier=tfstride-app",
            "flow_log_state=not_configured",
            "network=google_compute_network.main.id",
            "project=tfstride-demo"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 0,
        "lateral_movement": 2,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:7f9b36a6593edd523470255de4c3c4dd97f9b9004e2fe64bc257be0bb37d1453",
      "title": "GCS bucket does not enforce Public Access Prevention",
      "rule_id": "gcp-gcs-public-access-prevention-not-enforced",
      "category": "Information Disclosure",
      "severity": "medium",
      "affected_resources": [
        "google_storage_bucket.logs"
      ],
      "trust_boundary_id": "internet-to-service:internet->google_storage_bucket.logs",
      "rationale": "google_storage_bucket.logs does not enforce GCS Public Access Prevention. Public principals can still be introduced through bucket IAM unless an organization-level policy blocks them.",
      "recommended_mitigation": "Set GCS Public Access Prevention to `enforced` on sensitive buckets and rely on explicit non-public identities or signed access patterns when objects must be shared.",
      "evidence": [
        {
          "key": "access_control_posture",
          "values": [
            "public_access_prevention is unset"
          ]
        },
        {
          "key": "public_exposure_reasons",
          "values": [
            "google_storage_bucket_iam_member.public_logs_reader grants roles/storage.objectViewer to allUsers"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:c40cdeca64a1e9283e86c379c3ef9e8a37ce2983381579cf7ab47eab05f62be9",
      "title": "GCS bucket is publicly accessible",
      "rule_id": "gcp-gcs-public-access",
      "category": "Information Disclosure",
      "severity": "medium",
      "affected_resources": [
        "google_storage_bucket.logs"
      ],
      "trust_boundary_id": "internet-to-service:internet->google_storage_bucket.logs",
      "rationale": "google_storage_bucket.logs is publicly reachable through GCS IAM grants. Public bucket access is a common source of unintended object disclosure.",
      "recommended_mitigation": "Remove `allUsers` and `allAuthenticatedUsers` from bucket-level IAM grants, enforce GCS Public Access Prevention, and use signed URLs, CDN origins, or narrow identities when objects must be distributed.",
      "evidence": [
        {
          "key": "public_exposure_reasons",
          "values": [
            "google_storage_bucket_iam_member.public_logs_reader grants roles/storage.objectViewer to allUsers"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:90b26f239387e86c12b711ddfccfd9c03f230b8db90b6d4f559178f63d5412d2",
      "title": "GCS sensitive bucket does not use customer-managed encryption",
      "rule_id": "gcp-gcs-customer-managed-encryption-missing",
      "category": "Information Disclosure",
      "severity": "medium",
      "affected_resources": [
        "google_storage_bucket.logs"
      ],
      "trust_boundary_id": null,
      "rationale": "google_storage_bucket.logs relies on default GCS encryption rather than a customer-managed KMS key. Sensitive buckets lose key ownership, rotation, and separation-of-duties controls that a CMEK can provide.",
      "recommended_mitigation": "Configure a Cloud KMS customer-managed key for sensitive GCS buckets, assign the GCS service agent only the key roles it needs, and manage key rotation separately from bucket IAM.",
      "evidence": [
        {
          "key": "encryption_posture",
          "values": [
            "default_kms_key_name is unset",
            "customer_managed_encryption is false"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:9a500cc3c8625c002b61bcdc1c12c2f93348dd2ad1f9371641b6c77d6f104942",
      "title": "GCS sensitive bucket retention policy is insufficient",
      "rule_id": "gcp-gcs-retention-policy-insufficient",
      "category": "Denial of Service",
      "severity": "medium",
      "affected_resources": [
        "google_storage_bucket.logs"
      ],
      "trust_boundary_id": null,
      "rationale": "google_storage_bucket.logs does not have deterministic GCS retention posture that meets the minimum retention threshold and lock expectation. Retention policy and retention lock reduce destructive deletion or overwrite risk, but are distinct from soft-delete recovery controls.",
      "recommended_mitigation": "Configure a GCS retention policy that meets recovery and compliance objectives, and lock the retention policy after operational validation. Treat retention lock as immutability posture, not as a replacement for object versioning or soft-delete recovery.",
      "evidence": [
        {
          "key": "retention_policy_issues",
          "values": [
            "retention_policy is missing"
          ]
        },
        {
          "key": "retention_policy_posture",
          "values": [
            "retention_policy.retention_period_state=missing",
            "minimum_retention_period_days=7",
            "minimum_retention_period_seconds=604800",
            "retention_policy.is_locked is unset"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:b581f92581ebad73170a679021871c1cdbef137bf69e170c5f0c4085af7665bc",
      "title": "GCS sensitive bucket versioning is disabled",
      "rule_id": "gcp-gcs-versioning-disabled",
      "category": "Denial of Service",
      "severity": "medium",
      "affected_resources": [
        "google_storage_bucket.logs"
      ],
      "trust_boundary_id": null,
      "rationale": "google_storage_bucket.logs stores sensitive GCS data without bucket versioning. Accidental overwrites, deletes, or destructive changes have fewer object-level recovery options.",
      "recommended_mitigation": "Enable bucket versioning for sensitive GCS buckets and pair it with lifecycle retention rules that match recovery objectives and storage cost constraints.",
      "evidence": [
        {
          "key": "data_protection_posture",
          "values": [
            "versioning.enabled is false",
            "data_sensitivity is sensitive"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:ab43539343dcf75b3f251a3a1484170adfcca5cc88c75ff887216f7468a33d73",
      "title": "GKE cluster does not enable Workload Identity",
      "rule_id": "gcp-gke-workload-identity-disabled",
      "category": "Elevation of Privilege",
      "severity": "medium",
      "affected_resources": [
        "google_container_cluster.app"
      ],
      "trust_boundary_id": null,
      "rationale": "google_container_cluster.app does not enable GKE Workload Identity. Pods are more likely to depend on node service-account credentials, which weakens workload-level identity boundaries and can expand blast radius after pod compromise.",
      "recommended_mitigation": "Enable GKE Workload Identity, bind Kubernetes service accounts to narrow Google service accounts, and avoid relying on node service-account credentials for pod-level cloud API access.",
      "evidence": [
        {
          "key": "workload_identity_posture",
          "values": [
            "workload_identity_enabled is false",
            "workload_pool is unset"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 1,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:b537e7c77bbbdae8be9a179e67af423e9a5b0f8de5887a3ccec1daedd43a6c8d",
      "title": "GKE cluster exposes a public control plane",
      "rule_id": "gcp-gke-public-control-plane",
      "category": "Spoofing",
      "severity": "medium",
      "affected_resources": [
        "google_container_cluster.app"
      ],
      "trust_boundary_id": "internet-to-service:internet->google_container_cluster.app",
      "rationale": "google_container_cluster.app exposes a public GKE control-plane endpoint. Public API server reachability increases dependence on IAM, Kubernetes RBAC, and authorized network configuration to protect cluster administration.",
      "recommended_mitigation": "Use private GKE control-plane endpoints where possible, or restrict master authorized networks to narrow administrator CIDRs and enforce IAM plus Kubernetes RBAC for cluster administration.",
      "evidence": [
        {
          "key": "control_plane_endpoint",
          "values": [
            "35.4.5.6"
          ]
        },
        {
          "key": "public_access_reasons",
          "values": [
            "GKE control plane endpoint is public"
          ]
        },
        {
          "key": "public_exposure_reasons",
          "values": [
            "authorized network `anywhere` allows 0.0.0.0/0"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 4,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:09c2cc33834f67067bd128eb62e7603601289333acea86f0addf98ae6e2875a0",
      "title": "GKE control plane allows broad authorized networks",
      "rule_id": "gcp-gke-broad-authorized-networks",
      "category": "Spoofing",
      "severity": "medium",
      "affected_resources": [
        "google_container_cluster.app"
      ],
      "trust_boundary_id": "internet-to-service:internet->google_container_cluster.app",
      "rationale": "google_container_cluster.app exposes the GKE control plane without narrow master authorized networks. Internet-wide or unset CIDR controls leave the Kubernetes API server reachable from untrusted client networks.",
      "recommended_mitigation": "Configure GKE master authorized networks with narrow trusted CIDRs, avoid internet-wide ranges, and prefer private control-plane access for administrative paths.",
      "evidence": [
        {
          "key": "authorized_networks",
          "values": [
            "anywhere (0.0.0.0/0)"
          ]
        },
        {
          "key": "configured_authorized_network_count",
          "values": [
            "1"
          ]
        },
        {
          "key": "public_exposure_reasons",
          "values": [
            "authorized network `anywhere` allows 0.0.0.0/0"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 0,
        "lateral_movement": 2,
        "blast_radius": 1,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:9ca59f8d3902cf9c5676387f99ec2abe8a30e29ef807dd80c415f8e22cf0a3db",
      "title": "GKE control-plane logging is incomplete",
      "rule_id": "gcp-gke-control-plane-logging-incomplete",
      "category": "Repudiation",
      "severity": "medium",
      "affected_resources": [
        "google_container_cluster.app"
      ],
      "trust_boundary_id": null,
      "rationale": "google_container_cluster.app does not show deterministic GKE control-plane logging for key security components. Missing API server, scheduler, or controller manager logs can limit investigation of administrative and cluster-control activity.",
      "recommended_mitigation": "Enable GKE control-plane logging for security-relevant components such as the API server, scheduler, and controller manager, and retain the logs in a monitored logging project.",
      "evidence": [
        {
          "key": "logging_posture",
          "values": [
            "control_plane_logging_state=not_configured",
            "logging_service is not represented in planned values",
            "logging_components are not represented in planned values",
            "control-plane logging is not_configured"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 0,
        "lateral_movement": 2,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:9c631f94bf79e6ebab096db158af05bf844349c8b290c283c685e2f833c72d06",
      "title": "GKE network policy is not enabled",
      "rule_id": "gcp-gke-network-policy-disabled",
      "category": "Tampering",
      "severity": "medium",
      "affected_resources": [
        "google_container_cluster.app"
      ],
      "trust_boundary_id": null,
      "rationale": "google_container_cluster.app does not deterministically enable GKE network policy. Without a pod network policy provider, Kubernetes workloads have weaker pod-level traffic isolation and lateral-movement controls.",
      "recommended_mitigation": "Enable a supported GKE network policy provider and define namespace or workload policies that restrict pod-to-pod and pod-to-service traffic paths.",
      "evidence": [
        {
          "key": "network_policy_posture",
          "values": [
            "network_policy_state=not_configured",
            "network_policy_provider is not represented in planned values"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 0,
        "lateral_movement": 2,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:e0bcd72328ae6eaccc85432adb6e6c3e10ecfb9105b3abbb78b7c6e4216414a0",
      "title": "GKE node metadata exposure is not hardened",
      "rule_id": "gcp-gke-legacy-metadata-endpoints-enabled",
      "category": "Elevation of Privilege",
      "severity": "medium",
      "affected_resources": [
        "google_container_node_pool.app"
      ],
      "trust_boundary_id": null,
      "rationale": "google_container_node_pool.app allows legacy or broad node metadata exposure. Workloads on the node may be able to reach metadata credentials outside the intended GKE metadata server controls.",
      "recommended_mitigation": "Disable legacy metadata endpoints, use GKE metadata server or Workload Identity controls, and prevent pods from reaching broad node credentials.",
      "evidence": [
        {
          "key": "node_metadata_posture",
          "values": [
            "legacy metadata endpoints are enabled",
            "metadata mode is GCE_METADATA"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 1,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:fea5027c6093d61329e1e6df2330ed36fa41f648897ac36c2e59e884df443042",
      "title": "GKE secrets encryption is not configured",
      "rule_id": "gcp-gke-secrets-encryption-not-configured",
      "category": "Information Disclosure",
      "severity": "medium",
      "affected_resources": [
        "google_container_cluster.app"
      ],
      "trust_boundary_id": null,
      "rationale": "google_container_cluster.app does not show deterministic GKE application-layer secrets encryption with a Cloud KMS key. Kubernetes secrets may not have customer-controlled encryption key ownership represented in the Terraform plan.",
      "recommended_mitigation": "Configure GKE application-layer secrets encryption with a Cloud KMS key where customer key ownership or stronger Kubernetes secret protection is required.",
      "evidence": [
        {
          "key": "secret_encryption_posture",
          "values": [
            "secrets_encryption_state=disabled",
            "database_encryption_state is not represented in planned values",
            "database_encryption_key_name is not represented in planned values"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:25baec6d5d59ab0812b7ae507724a6f346e47d121edc5a074b9266bb39958f0f",
      "title": "Internet-exposed GCP compute instance permits broad ingress",
      "rule_id": "gcp-public-compute-broad-ingress",
      "category": "Spoofing",
      "severity": "medium",
      "affected_resources": [
        "google_compute_instance.web",
        "google_compute_firewall.public_admin"
      ],
      "trust_boundary_id": "internet-to-service:internet->google_compute_instance.web",
      "rationale": "google_compute_instance.web has an external access config and matching GCP firewall rules allow administrative access or all ports from the public internet. That broad ingress raises the chance of unauthenticated probing and credential attacks.",
      "recommended_mitigation": "Restrict GCP firewall source ranges and exposed ports, remove external IP access where possible, and use Identity-Aware Proxy, VPN, or a controlled bastion for administration.",
      "evidence": [
        {
          "key": "firewall_rules",
          "values": [
            "google_compute_firewall.public_admin ingress tcp 22 from 0.0.0.0/0",
            "google_compute_firewall.public_admin ingress tcp 3389 from 0.0.0.0/0"
          ]
        },
        {
          "key": "network_tags",
          "values": [
            "web"
          ]
        },
        {
          "key": "internet_ingress_reasons",
          "values": [
            "google_compute_firewall.public_admin ingress tcp 22 from 0.0.0.0/0",
            "google_compute_firewall.public_admin ingress tcp 3389 from 0.0.0.0/0",
            "google_compute_firewall.public_all ingress tcp unspecified ports from 0.0.0.0/0"
          ]
        },
        {
          "key": "public_exposure_reasons",
          "values": [
            "compute instance has an external access config and matching firewall rules allow internet ingress"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 4,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:9cffb8d448336f1a502e2dc72413c93d27369f9794c560a2742552b8602992b6",
      "title": "Pub/Sub subscription does not configure a dead-letter policy",
      "rule_id": "gcp-pubsub-subscription-dead-letter-policy-missing",
      "category": "Denial of Service",
      "severity": "medium",
      "affected_resources": [
        "google_pubsub_subscription.events"
      ],
      "trust_boundary_id": null,
      "rationale": "google_pubsub_subscription.events does not configure a Pub/Sub dead-letter policy. Poison messages or repeated delivery failures can consume subscriber capacity and reduce recovery options for failed processing.",
      "recommended_mitigation": "Configure a reviewed Pub/Sub dead-letter topic and delivery-attempt threshold for subscriptions where poison messages or repeated delivery failures could disrupt processing.",
      "evidence": [
        {
          "key": "target_resource",
          "values": [
            "address=google_pubsub_subscription.events",
            "resource_type=google_pubsub_subscription"
          ]
        },
        {
          "key": "dead_letter_posture",
          "values": [
            "dead_letter_policy_state=not_configured",
            "dead_letter_topic=unset"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:87622623c501ede23c62e92e63616b8e9fe19bc701d031de917f19757d61bcc9",
      "title": "Pub/Sub topic does not use customer-managed encryption",
      "rule_id": "gcp-pubsub-topic-customer-managed-encryption-missing",
      "category": "Information Disclosure",
      "severity": "medium",
      "affected_resources": [
        "google_pubsub_topic.events"
      ],
      "trust_boundary_id": null,
      "rationale": "google_pubsub_topic.events relies on Google-managed Pub/Sub encryption rather than a customer-managed Cloud KMS key. Google-managed encryption still protects message data; this finding concerns key ownership, rotation, audit separation, and compliance posture.",
      "recommended_mitigation": "Configure a customer-managed Cloud KMS key for sensitive Pub/Sub topics where key ownership, rotation, audit separation, or compliance requirements warrant it.",
      "evidence": [
        {
          "key": "target_resource",
          "values": [
            "address=google_pubsub_topic.events",
            "resource_type=google_pubsub_topic"
          ]
        },
        {
          "key": "encryption_ownership",
          "values": [
            "cmek_state=not_configured",
            "kms_key_name=unset"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:2cb0283d7cd0a3c2bcd90a345b80a5779aea5392cfd8535aff986da5d44d0a10",
      "title": "Secret Manager lifecycle posture is incomplete",
      "rule_id": "gcp-secret-manager-lifecycle-posture-incomplete",
      "category": "Denial of Service",
      "severity": "medium",
      "affected_resources": [
        "google_secret_manager_secret.api_key"
      ],
      "trust_boundary_id": null,
      "rationale": "google_secret_manager_secret.api_key does not show deterministic Secret Manager lifecycle posture for secret expiry or delayed version destruction. Expiry and version-destroy TTL controls reduce the lifetime of stale or accidentally destroyed secret material, but do not replace access review or rotation.",
      "recommended_mitigation": "Configure Secret Manager `ttl` or `expire_time` where secret-level expiry is expected, and set `version_destroy_ttl` to a retention window that gives operators enough time to recover from accidental or malicious secret version destruction.",
      "evidence": [
        {
          "key": "target_resource",
          "values": [
            "address=google_secret_manager_secret.api_key",
            "type=google_secret_manager_secret",
            "identifier=projects/tfstride-demo/secrets/tfstride-api-key"
          ]
        },
        {
          "key": "lifecycle_issues",
          "values": [
            "secret has no ttl, expire_time, or version_destroy_ttl lifecycle guardrail",
            "version_destroy_ttl is missing"
          ]
        },
        {
          "key": "lifecycle_posture",
          "values": [
            "ttl=unset",
            "expire_time=unset",
            "version_destroy_ttl=unset",
            "minimum_version_destroy_ttl_days=7",
            "minimum_version_destroy_ttl_seconds=604800"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:b3893099e06aad5adc9f9094188a13dc66675541dedccfd9636175998fb0ff8a",
      "title": "Secret Manager secret does not use customer-managed encryption",
      "rule_id": "gcp-secret-manager-customer-managed-encryption-missing",
      "category": "Information Disclosure",
      "severity": "medium",
      "affected_resources": [
        "google_secret_manager_secret.api_key"
      ],
      "trust_boundary_id": null,
      "rationale": "google_secret_manager_secret.api_key relies on Google-managed Secret Manager encryption rather than a customer-managed Cloud KMS key. Google-managed encryption still applies; this finding concerns customer key ownership, rotation, audit separation, and compliance posture for sensitive secrets.",
      "recommended_mitigation": "Configure Secret Manager replication with Cloud KMS customer-managed encryption for secrets that require customer key ownership, independent rotation, audit separation, or compliance controls.",
      "evidence": [
        {
          "key": "target_resource",
          "values": [
            "address=google_secret_manager_secret.api_key",
            "type=google_secret_manager_secret",
            "identifier=projects/tfstride-demo/secrets/tfstride-api-key"
          ]
        },
        {
          "key": "encryption_ownership",
          "values": [
            "customer_managed_encryption is false",
            "secret_manager_replication_mode=automatic",
            "secret_manager_kms_key_names is empty"
          ]
        },
        {
          "key": "replication_posture",
          "values": [
            "replication.mode=automatic"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:408c558dd93f32bfca75eea24d9787a2feaab97ff26e4a869e7984cda37b5bd3",
      "title": "Sensitive GCP resource IAM binding allows broad or external access",
      "rule_id": "gcp-sensitive-resource-iam-external-access",
      "category": "Information Disclosure",
      "severity": "medium",
      "affected_resources": [
        "google_kms_crypto_key.customer",
        "google_kms_crypto_key_iam_member.partner_decrypter"
      ],
      "trust_boundary_id": null,
      "rationale": "google_kms_crypto_key.customer grants `roles/cloudkms.cryptoKeyDecrypter` to `serviceAccount:decryptor@partner-project.iam.gserviceaccount.com` through GCP IAM. Public, broad-domain, or foreign-project principals can access sensitive secrets or cryptographic key operations outside the expected project trust boundary.",
      "recommended_mitigation": "Grant Secret Manager and Cloud KMS IAM roles only to specific in-project service accounts or groups, remove public principals, and require explicit cross-project access reviews for partner identities.",
      "evidence": [
        {
          "key": "iam_binding",
          "values": [
            "source=google_kms_crypto_key_iam_member.partner_decrypter",
            "role=roles/cloudkms.cryptoKeyDecrypter",
            "member=serviceAccount:decryptor@partner-project.iam.gserviceaccount.com"
          ]
        },
        {
          "key": "trust_scope",
          "values": [
            "service account belongs to project `partner-project`, outside resource project `tfstride-demo`"
          ]
        },
        {
          "key": "resource_policy_sources",
          "values": [
            "google_kms_crypto_key_iam_member.partner_decrypter"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 1,
        "data_sensitivity": 2,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:bc42b57b554dae3294170371629f2e9f3f5261aa2a8a8782d328bc32c7c11f36",
      "title": "GKE Shielded Nodes is not enabled",
      "rule_id": "gcp-gke-shielded-nodes-disabled-or-unknown",
      "category": "Tampering",
      "severity": "low",
      "affected_resources": [
        "google_container_cluster.app"
      ],
      "trust_boundary_id": null,
      "rationale": "google_container_cluster.app does not show GKE Shielded Nodes enabled. Shielded Nodes add node integrity protections that reduce the impact of boot-level tampering and host compromise paths.",
      "recommended_mitigation": "Enable GKE Shielded Nodes to add node integrity protections against boot-level tampering and host compromise paths.",
      "evidence": [
        {
          "key": "shielded_nodes_posture",
          "values": [
            "shielded_nodes_state=unknown",
            "shielded nodes setting is not represented in planned values"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 0,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 1,
        "severity": "low",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:395842b3750772cd7178d7a0af98a4d201dc92331f52b1ba2e65361df75aff11",
      "title": "GKE legacy ABAC is enabled or unknown",
      "rule_id": "gcp-gke-legacy-abac-enabled-or-unknown",
      "category": "Elevation of Privilege",
      "severity": "low",
      "affected_resources": [
        "google_container_cluster.app"
      ],
      "trust_boundary_id": null,
      "rationale": "google_container_cluster.app does not show legacy ABAC disabled. Legacy ABAC can bypass stronger IAM and Kubernetes RBAC expectations, and an unknown Terraform value should be reviewed before relying on RBAC-only authorization.",
      "recommended_mitigation": "Disable legacy ABAC and rely on Kubernetes RBAC with centralized IAM-backed administration. Review unknown ABAC values before treating the cluster authorization posture as hardened.",
      "evidence": [
        {
          "key": "legacy_abac_posture",
          "values": [
            "legacy_abac_state=unknown",
            "enable_legacy_abac is not represented in planned values"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 0,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 1,
        "severity": "low",
        "computed_severity": null
      }
    }
  ],
  "suppressed_findings": [],
  "baselined_findings": [],
  "observations": [],
  "limitations": [
    "GCP support covers a curated set of compute, serverless, data, IAM, Kubernetes, networking, audit, private-connectivity, messaging, registry, and key-management resources. Analysis is plan-local and does not model every provider resource, runtime drift, or every organization-level control; provider-specific positive observations remain more limited than finding coverage.",
    "The engine reasons over Terraform planned values only and does not validate runtime drift, CloudTrail evidence, or post-deploy control-plane activity."
  ]
}
Markdown report
# GCP Nightmare Plan Demo

- Analyzed file: `sample_gcp_nightmare_plan.json`
- Provider: `gcp`
- Normalized resources: `31`
- Unsupported resources: `0`

## Summary

This run identified **9 trust boundaries** and **45 findings** across **31 normalized resources**.

- High severity findings: `14`
- Medium severity findings: `29`
- Low severity findings: `2`

## Analysis Coverage

- Terraform resources seen: `31`
- Provider resources considered: `31`
- Normalized resources: `31`
- Unsupported resources: `0`
- Registered provider rules (GCP): `78`
- Enabled provider rules (GCP): `78`
- Disabled rules: `0`
- Severity overrides: `0`
- Unresolved in-plan references: `0`
- Findings by rule:
  - `gcp-sensitive-resource-iam-external-access`: `2`
  - `gcp-pubsub-public-access`: `1`
  - `gcp-pubsub-topic-customer-managed-encryption-missing`: `1`
  - `gcp-pubsub-subscription-dead-letter-policy-missing`: `1`
  - `gcp-bigquery-public-access`: `1`
  - `gcp-cloud-sql-public-authorized-network`: `1`
  - `gcp-cloud-sql-backup-disabled`: `1`
  - `gcp-cloud-sql-public-ip-without-private-network`: `1`
  - `gcp-cloud-sql-ssl-not-required`: `1`
  - `gcp-cloud-sql-deletion-protection-disabled`: `1`
  - `gcp-cloud-sql-zonal-availability`: `1`
  - `gcp-gcs-public-access`: `1`
  - `gcp-gcs-public-access-prevention-not-enforced`: `1`
  - `gcp-gcs-versioning-disabled`: `1`
  - `gcp-gcs-customer-managed-encryption-missing`: `1`
  - `gcp-gcs-retention-policy-insufficient`: `1`
  - `gcp-secret-manager-customer-managed-encryption-missing`: `1`
  - `gcp-secret-manager-lifecycle-posture-incomplete`: `1`
  - `gcp-public-compute-broad-ingress`: `1`
  - `gcp-compute-os-login-disabled`: `1`
  - `gcp-gke-public-control-plane`: `1`
  - `gcp-gke-broad-authorized-networks`: `1`
  - `gcp-gke-workload-identity-disabled`: `1`
  - `gcp-gke-legacy-metadata-endpoints-enabled`: `1`
  - `gcp-gke-broad-node-service-account`: `1`
  - `gcp-gke-control-plane-logging-incomplete`: `1`
  - `gcp-subnetwork-flow-logs-not-configured`: `1`
  - `gcp-gke-network-policy-disabled`: `1`
  - `gcp-gke-secrets-encryption-not-configured`: `1`
  - `gcp-gke-legacy-abac-enabled-or-unknown`: `1`
  - `gcp-gke-shielded-nodes-disabled-or-unknown`: `1`
  - `gcp-cloud-run-public-invoker`: `1`
  - `gcp-cloud-functions-public-invoker`: `1`
  - `gcp-service-account-key-hygiene`: `1`
  - `gcp-service-account-key-effective-access`: `1`
  - `gcp-org-folder-iam-broad-principal`: `1`
  - `gcp-org-folder-iam-privileged-role`: `1`
  - `gcp-project-iam-broad-principal`: `1`
  - `gcp-project-iam-privileged-role`: `1`
  - `gcp-inherited-iam-sensitive-resource-access`: `1`
  - `gcp-inherited-iam-blast-radius`: `1`
  - `gcp-public-workload-sensitive-data-access`: `3`

## Discovered Trust Boundaries

### `internet-to-service`

- Source: `internet`
- Target: `google_compute_instance.web`
- Description: Traffic can cross from the public internet to google_compute_instance.web.
- Rationale: The resource is directly reachable or intentionally exposed to unauthenticated network clients.

### `internet-to-service`

- Source: `internet`
- Target: `google_container_cluster.app`
- Description: Traffic can cross from the public internet to google_container_cluster.app.
- Rationale: The resource is directly reachable or intentionally exposed to unauthenticated network clients.

### `internet-to-service`

- Source: `internet`
- Target: `google_sql_database_instance.app`
- Description: Traffic can cross from the public internet to google_sql_database_instance.app.
- Rationale: The resource is directly reachable or intentionally exposed to unauthenticated network clients.

### `internet-to-service`

- Source: `internet`
- Target: `google_storage_bucket.logs`
- Description: Traffic can cross from the public internet to google_storage_bucket.logs.
- Rationale: The resource is directly reachable or intentionally exposed to unauthenticated network clients.

### `internet-to-service`

- Source: `internet`
- Target: `google_cloud_run_v2_service.api`
- Description: Traffic can cross from the public internet to google_cloud_run_v2_service.api.
- Rationale: The resource is directly reachable or intentionally exposed to unauthenticated network clients.

### `internet-to-service`

- Source: `internet`
- Target: `google_cloudfunctions_function.worker`
- Description: Traffic can cross from the public internet to google_cloudfunctions_function.worker.
- Rationale: The resource is directly reachable or intentionally exposed to unauthenticated network clients.

### `workload-to-data-store`

- Source: `google_compute_instance.web`
- Target: `google_bigquery_dataset.analytics`
- Description: google_compute_instance.web can interact with google_bigquery_dataset.analytics.
- Rationale: GCP workloads cross into a higher-sensitivity data plane when their attached service account is granted data access through IAM: google_bigquery_dataset_iam_binding.analytics_viewers grants roles/bigquery.dataViewer to serviceAccount:tfstride-web@example.iam.gserviceaccount.com.

### `workload-to-data-store`

- Source: `google_cloud_run_v2_service.api`
- Target: `google_sql_database_instance.app`
- Description: google_cloud_run_v2_service.api can interact with google_sql_database_instance.app.
- Rationale: Application or function workloads cross into a higher-sensitivity data plane when a directly internet-reachable database is reachable from a workload subnet with general egress.

### `workload-to-data-store`

- Source: `google_cloudfunctions_function.worker`
- Target: `google_sql_database_instance.app`
- Description: google_cloudfunctions_function.worker can interact with google_sql_database_instance.app.
- Rationale: Application or function workloads cross into a higher-sensitivity data plane when a directly internet-reachable database is reachable from a workload subnet with general egress.

## Findings

### High

#### BigQuery IAM binding allows public or broad data access

- STRIDE category: Information Disclosure
- Affected resources: `google_bigquery_dataset.analytics`, `google_bigquery_dataset_iam_binding.analytics_viewers`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +2, privilege_breadth +2, data_sensitivity +2, lateral_movement +1, blast_radius +2, final_score 9 => high
- Rationale: google_bigquery_dataset.analytics grants `roles/bigquery.dataViewer` to `allUsers` through BigQuery IAM. Public or broad principals can read or modify analytical data outside the expected project trust boundary.
- Recommended mitigation: Grant BigQuery dataset and table access only to specific in-project identities or reviewed analytics groups, remove public principals, and prefer least-privilege data roles.
- Evidence:
  - iam binding: source=google_bigquery_dataset_iam_binding.analytics_viewers; role=roles/bigquery.dataViewer; member=allUsers
  - trust scope: member is public GCP principal `allUsers`
  - resource policy sources: google_bigquery_dataset_iam_binding.analytics_viewers

#### Cloud SQL instance accepts public authorized network access

- STRIDE category: Information Disclosure
- Affected resources: `google_sql_database_instance.app`
- Trust boundary: `internet-to-service:internet->google_sql_database_instance.app`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +2, lateral_movement +1, blast_radius +1, final_score 6 => high
- Rationale: google_sql_database_instance.app has a public Cloud SQL IPv4 endpoint and an authorized network that allows internet-wide client sources. That weakens the database trust boundary even when database authentication is still required.
- Recommended mitigation: Disable public IPv4 access where possible, use private IP connectivity or the Cloud SQL Auth Proxy, and restrict authorized networks to narrow CIDRs when public client access is required.
- Evidence:
  - authorized networks: anywhere (0.0.0.0/0)
  - public exposure reasons: authorized network `anywhere` allows 0.0.0.0/0

#### GCP organization or folder IAM grants a high-privilege role

- STRIDE category: Elevation of Privilege
- Affected resources: `google_folder_iam_member.folder_admin`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +2, data_sensitivity +0, lateral_movement +2, blast_radius +2, final_score 6 => high
- Rationale: google_folder_iam_member.folder_admin grants the high-impact GCP role `roles/resourcemanager.folderAdmin` to `group:folder-admins@example.com` at folder scope `folders/12345`. That role enables folder hierarchy administration across a high-level resource boundary and can materially expand blast radius if the principal is compromised.
- Recommended mitigation: Replace high-impact organization and folder roles with narrowly scoped custom or predefined roles, assign them only to controlled break-glass or platform groups, and review descendant project blast radius.
- Evidence:
  - iam binding: member=group:folder-admins@example.com; role=roles/resourcemanager.folderAdmin
  - scope: folder scope `folders/12345`
  - role risk: folder hierarchy administration

#### GCP organization or folder IAM grants access to broad principals

- STRIDE category: Elevation of Privilege
- Affected resources: `google_organization_iam_binding.domain_viewer`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +2, data_sensitivity +0, lateral_movement +2, blast_radius +2, final_score 6 => high
- Rationale: google_organization_iam_binding.domain_viewer grants `roles/viewer` to `domain:example.com` at organization scope `1234567890`. Public or broad-domain principals at organization or folder scope can expand access across many descendant projects and workloads.
- Recommended mitigation: Remove public and broad-domain principals from organization and folder IAM, grant high-level access only to tightly controlled groups, and prefer project- or resource-scoped bindings where possible.
- Evidence:
  - iam binding: member=domain:example.com; role=roles/viewer
  - scope: organization scope `1234567890`
  - trust scope: member grants a whole Google Workspace domain

#### GCP project IAM binding grants a high-privilege role

- STRIDE category: Elevation of Privilege
- Affected resources: `google_project_iam_member.public_owner`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +2, data_sensitivity +0, lateral_movement +2, blast_radius +2, final_score 6 => high
- Rationale: google_project_iam_member.public_owner grants the high-impact GCP role `roles/owner` to `allUsers` at project scope. That role enables full project administration and can materially expand control-plane blast radius if the principal is compromised or mis-scoped.
- Recommended mitigation: Replace Owner, Editor, IAM admin, service-account impersonation, and admin-class project roles with narrowly scoped predefined or custom roles assigned to specific groups or service accounts.
- Evidence:
  - iam binding: member=allUsers; role=roles/owner
  - role risk: full project administration

#### GCP service account key can exercise sensitive or privileged access

- STRIDE category: Elevation of Privilege
- Affected resources: `google_service_account.web`, `google_service_account_key.web`, `google_bigquery_dataset.analytics`, `google_bigquery_dataset_iam_binding.analytics_viewers`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +1, data_sensitivity +2, lateral_movement +1, blast_radius +2, final_score 6 => high
- Rationale: google_service_account_key.web creates portable credentials for `google_service_account.web`, and that service account has sensitive data access or high-impact IAM grants. A copied key can exercise those effective permissions outside the intended workload boundary.
- Recommended mitigation: Remove sensitive data and high-impact IAM grants from service accounts that still have user-managed keys, replace keys with workload identity or service-account impersonation, and revoke or rotate existing keys after privilege reduction.
- Evidence:
  - key context: source=google_service_account_key.web; service_account_reference=google_service_account.web.email; resolved_service_account=google_service_account.web
  - service account principals: serviceAccount:tfstride-web@example.iam.gserviceaccount.com; tfstride-web@example.iam.gserviceaccount.com
  - effective access: resource=google_bigquery_dataset.analytics; source=google_bigquery_dataset_iam_binding.analytics_viewers; scope=BigQuery dataset IAM; role=roles/bigquery.dataViewer; member=serviceAccount:tfstride-web@example.iam.gserviceaccount.com; risk=BigQuery dataset IAM grants roles/bigquery.dataViewer

#### GKE node pool uses broad node identity settings

- STRIDE category: Elevation of Privilege
- Affected resources: `google_container_node_pool.app`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +2, data_sensitivity +0, lateral_movement +2, blast_radius +2, final_score 6 => high
- Rationale: google_container_node_pool.app uses broad GKE node identity settings. Default or broadly scoped node service accounts can turn a node or pod compromise into wider GCP API access.
- Recommended mitigation: Attach a dedicated least-privilege node service account, remove cloud-platform or full-control OAuth scopes, and shift workload permissions to Workload Identity bindings.
- Evidence:
  - node identity risks: node service account uses default Compute Engine identity `123456789-compute@developer.gserviceaccount.com`; node OAuth scope is broad: https://www.googleapis.com/auth/cloud-platform
  - node service account: 123456789-compute@developer.gserviceaccount.com
  - oauth scopes: https://www.googleapis.com/auth/cloud-platform

#### Inherited GCP IAM grant expands descendant blast radius

- STRIDE category: Elevation of Privilege
- Affected resources: `google_project_iam_member.public_owner`, `google_bigquery_dataset.analytics`, `google_bigquery_table.events`, `google_cloud_run_v2_service.api`, `google_cloudfunctions_function.worker`, `google_compute_firewall.public_admin`, `google_compute_firewall.public_all`, `google_compute_instance.web`, `google_compute_network.main`, `google_compute_route.default_internet`, `google_compute_subnetwork.app`, `google_container_cluster.app`, `google_container_node_pool.app`, `google_kms_crypto_key.customer`, `google_logging_project_sink.processor`, `google_pubsub_subscription.events`, `google_pubsub_topic.events`, `google_secret_manager_secret.api_key`, `google_service_account.web`, `google_service_account_key.web`, `google_sql_database_instance.app`, `google_storage_bucket.logs`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +2, privilege_breadth +2, data_sensitivity +2, lateral_movement +2, blast_radius +2, final_score 10 => high
- Rationale: google_project_iam_member.public_owner grants `roles/owner` to `allUsers` at project scope `tfstride-demo`, and that inherited grant applies to 21 concrete descendant resource(s). A high-level IAM grant with broad, external, or high-impact access increases control-plane blast radius because compromise or misuse can affect resources below the inherited scope.
- Recommended mitigation: Avoid broad or high-impact IAM grants at organization, folder, and project scope when narrower resource-level or workload-specific bindings are possible; split inherited roles by service and review descendant resources before assigning public, external, or administrator principals.
- Evidence:
  - iam binding: source=google_project_iam_member.public_owner; scope=project:tfstride-demo; member=allUsers; role=roles/owner
  - role risk: full project administration
  - trust scope: member is public GCP principal `allUsers`
  - descendant scope: scope=project:tfstride-demo; descendant_count=21; resource_type_count=20; projects=tfstride-demo
  - descendant resource types: google_bigquery_dataset: 1; google_bigquery_table: 1; google_cloud_run_v2_service: 1; google_cloudfunctions_function: 1; google_compute_firewall: 2; google_compute_instance: 1; google_compute_network: 1; google_compute_route: 1; google_compute_subnetwork: 1; google_container_cluster: 1; google_container_node_pool: 1; google_kms_crypto_key: 1; google_logging_project_sink: 1; google_pubsub_subscription: 1; google_pubsub_topic: 1; google_secret_manager_secret: 1; google_service_account: 1; google_service_account_key: 1; google_sql_database_instance: 1; google_storage_bucket: 1
  - descendant resources: google_bigquery_dataset.analytics; google_bigquery_table.events; google_cloud_run_v2_service.api; google_cloudfunctions_function.worker; google_compute_firewall.public_admin; google_compute_firewall.public_all; google_compute_instance.web; google_compute_network.main; google_compute_route.default_internet; google_compute_subnetwork.app; and 11 more descendant resources

#### Inherited GCP IAM grant reaches sensitive resources

- STRIDE category: Information Disclosure
- Affected resources: `google_project_iam_member.public_owner`, `google_bigquery_dataset.analytics`, `google_bigquery_table.events`, `google_kms_crypto_key.customer`, `google_pubsub_subscription.events`, `google_pubsub_topic.events`, `google_secret_manager_secret.api_key`, `google_sql_database_instance.app`, `google_storage_bucket.logs`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +2, privilege_breadth +2, data_sensitivity +2, lateral_movement +1, blast_radius +2, final_score 9 => high
- Rationale: google_project_iam_member.public_owner grants `roles/owner` to `allUsers` at project scope `tfstride-demo`, and that inherited grant reaches 8 sensitive GCP descendant resource(s). Project, folder, and organization IAM applies below the grant scope, so a single ancestor binding can expose data resources beyond their local IAM boundary.
- Recommended mitigation: Move sensitive data access off organization, folder, and project-level IAM where possible; grant Secret Manager, KMS, GCS, Cloud SQL, BigQuery, and Pub/Sub permissions at the narrowest resource scope with reviewed principals and custom roles.
- Evidence:
  - iam binding: source=google_project_iam_member.public_owner; scope=project:tfstride-demo; member=allUsers; role=roles/owner
  - sensitive descendants: resource=google_bigquery_dataset.analytics; type=google_bigquery_dataset; risk=BigQuery dataset data access through roles/owner; resource=google_bigquery_table.events; type=google_bigquery_table; risk=BigQuery table data access through roles/owner; resource=google_kms_crypto_key.customer; type=google_kms_crypto_key; risk=Cloud KMS cryptographic key access through roles/owner; resource=google_pubsub_subscription.events; type=google_pubsub_subscription; risk=Pub/Sub subscription data access through roles/owner; resource=google_pubsub_topic.events; type=google_pubsub_topic; risk=Pub/Sub topic data access through roles/owner; resource=google_secret_manager_secret.api_key; type=google_secret_manager_secret; risk=Secret Manager secret access through roles/owner; resource=google_sql_database_instance.app; type=google_sql_database_instance; risk=Cloud SQL client/admin access through roles/owner; resource=google_storage_bucket.logs; type=google_storage_bucket; risk=GCS object data access through roles/owner
  - trust scope: member is public GCP principal `allUsers`

#### Internet-exposed GCP workload can access sensitive data services

- STRIDE category: Information Disclosure
- Affected resources: `google_cloud_run_v2_service.api`, `google_sql_database_instance.app`
- Trust boundary: `workload-to-data-store:google_cloud_run_v2_service.api->google_sql_database_instance.app`
- Severity reasoning: internet_exposure +2, privilege_breadth +1, data_sensitivity +2, lateral_movement +1, blast_radius +1, final_score 7 => high
- Rationale: google_cloud_run_v2_service.api is internet-exposed and runs with GCP workload identity serviceAccount:tfstride-run@tfstride-demo.iam.gserviceaccount.com. That identity can access google_sql_database_instance.app. A compromise of the public workload can therefore become direct access to sensitive GCP data services.
- Recommended mitigation: Run public GCP workloads with narrowly scoped service accounts, remove direct Secret Manager, Cloud KMS, GCS, or Cloud SQL grants from internet-facing instances, and broker sensitive data access through private services where possible.
- Evidence:
  - public exposure reasons: google_cloud_run_v2_service_iam_member.public_invoker grants roles/run.invoker to allUsers
  - workload identity: serviceAccount:tfstride-run@tfstride-demo.iam.gserviceaccount.com
  - data access path: google_cloud_run_v2_service.api reaches google_sql_database_instance.app
  - boundary rationale: Application or function workloads cross into a higher-sensitivity data plane when a directly internet-reachable database is reachable from a workload subnet with general egress.

#### Internet-exposed GCP workload can access sensitive data services

- STRIDE category: Information Disclosure
- Affected resources: `google_cloudfunctions_function.worker`, `google_sql_database_instance.app`
- Trust boundary: `workload-to-data-store:google_cloudfunctions_function.worker->google_sql_database_instance.app`
- Severity reasoning: internet_exposure +2, privilege_breadth +1, data_sensitivity +2, lateral_movement +1, blast_radius +1, final_score 7 => high
- Rationale: google_cloudfunctions_function.worker is internet-exposed and runs with GCP workload identity serviceAccount:tfstride-fn@tfstride-demo.iam.gserviceaccount.com. That identity can access google_sql_database_instance.app. A compromise of the public workload can therefore become direct access to sensitive GCP data services.
- Recommended mitigation: Run public GCP workloads with narrowly scoped service accounts, remove direct Secret Manager, Cloud KMS, GCS, or Cloud SQL grants from internet-facing instances, and broker sensitive data access through private services where possible.
- Evidence:
  - public exposure reasons: google_cloudfunctions_function_iam_member.public_invoker grants roles/cloudfunctions.invoker to allAuthenticatedUsers
  - workload identity: serviceAccount:tfstride-fn@tfstride-demo.iam.gserviceaccount.com
  - data access path: google_cloudfunctions_function.worker reaches google_sql_database_instance.app
  - boundary rationale: Application or function workloads cross into a higher-sensitivity data plane when a directly internet-reachable database is reachable from a workload subnet with general egress.

#### Internet-exposed GCP workload can access sensitive data services

- STRIDE category: Information Disclosure
- Affected resources: `google_compute_instance.web`, `google_bigquery_dataset.analytics`, `google_bigquery_dataset_iam_binding.analytics_viewers`
- Trust boundary: `workload-to-data-store:google_compute_instance.web->google_bigquery_dataset.analytics`
- Severity reasoning: internet_exposure +2, privilege_breadth +1, data_sensitivity +2, lateral_movement +1, blast_radius +1, final_score 7 => high
- Rationale: google_compute_instance.web is internet-exposed and runs with GCP workload identity serviceAccount:tfstride-web@example.iam.gserviceaccount.com. That identity can access google_bigquery_dataset.analytics. A compromise of the public workload can therefore become direct access to sensitive GCP data services.
- Recommended mitigation: Run public GCP workloads with narrowly scoped service accounts, remove direct Secret Manager, Cloud KMS, GCS, or Cloud SQL grants from internet-facing instances, and broker sensitive data access through private services where possible.
- Evidence:
  - public exposure reasons: compute instance has an external access config and matching firewall rules allow internet ingress
  - workload identity: serviceAccount:tfstride-web@example.iam.gserviceaccount.com
  - workload identity scopes: cloud-platform
  - data access path: google_compute_instance.web reaches google_bigquery_dataset.analytics
  - boundary rationale: GCP workloads cross into a higher-sensitivity data plane when their attached service account is granted data access through IAM: google_bigquery_dataset_iam_binding.analytics_viewers grants roles/bigquery.dataViewer to serviceAccount:tfstride-web@example.iam.gserviceaccount.com.
  - resource policy sources: google_bigquery_dataset_iam_binding.analytics_viewers

#### Pub/Sub IAM binding allows public or broad data access

- STRIDE category: Information Disclosure
- Affected resources: `google_pubsub_topic.events`, `google_pubsub_topic_iam_member.public_publisher`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +2, privilege_breadth +2, data_sensitivity +1, lateral_movement +1, blast_radius +1, final_score 7 => high
- Rationale: google_pubsub_topic.events grants `roles/pubsub.publisher` to `allAuthenticatedUsers` through Pub/Sub IAM. Public or broad principals can publish, consume, or administer event streams outside the expected service boundary.
- Recommended mitigation: Grant Pub/Sub publisher and subscriber roles only to specific service accounts or groups, remove public principals, and separate publish and consume permissions by workload.
- Evidence:
  - iam binding: source=google_pubsub_topic_iam_member.public_publisher; role=roles/pubsub.publisher; member=allAuthenticatedUsers
  - trust scope: member is public GCP principal `allAuthenticatedUsers`
  - resource policy sources: google_pubsub_topic_iam_member.public_publisher

#### Sensitive GCP resource IAM binding allows broad or external access

- STRIDE category: Information Disclosure
- Affected resources: `google_secret_manager_secret.api_key`, `google_secret_manager_secret_iam_member.public_accessor`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +2, privilege_breadth +2, data_sensitivity +2, lateral_movement +1, blast_radius +2, final_score 9 => high
- Rationale: google_secret_manager_secret.api_key grants `roles/secretmanager.secretAccessor` to `allAuthenticatedUsers` through GCP IAM. Public, broad-domain, or foreign-project principals can access sensitive secrets or cryptographic key operations outside the expected project trust boundary.
- Recommended mitigation: Grant Secret Manager and Cloud KMS IAM roles only to specific in-project service accounts or groups, remove public principals, and require explicit cross-project access reviews for partner identities.
- Evidence:
  - iam binding: source=google_secret_manager_secret_iam_member.public_accessor; role=roles/secretmanager.secretAccessor; member=allAuthenticatedUsers
  - trust scope: member is public GCP principal `allAuthenticatedUsers`
  - resource policy sources: google_secret_manager_secret_iam_member.public_accessor

### Medium

#### Cloud Functions function is publicly invokable

- STRIDE category: Spoofing
- Affected resources: `google_cloudfunctions_function.worker`, `google_cloudfunctions_function_iam_member.public_invoker`
- Trust boundary: `internet-to-service:internet->google_cloudfunctions_function.worker`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +0, lateral_movement +0, blast_radius +1, final_score 3 => medium
- Rationale: google_cloudfunctions_function.worker allows public HTTP access and grants Cloud Functions invoke permission to public GCP principals. Unauthenticated internet clients can reach the function entry point without an organization-owned identity boundary.
- Recommended mitigation: Remove `allUsers` and `allAuthenticatedUsers` from Cloud Functions invoker bindings unless anonymous access is intentional, and require authentication, IAP, API Gateway, or a controlled edge policy for public HTTP functions.
- Evidence:
  - public invoker bindings: source=google_cloudfunctions_function_iam_member.public_invoker; role=roles/cloudfunctions.invoker; member=allAuthenticatedUsers
  - public access reasons: google_cloudfunctions_function_iam_member.public_invoker grants roles/cloudfunctions.invoker to allAuthenticatedUsers
  - public exposure reasons: google_cloudfunctions_function_iam_member.public_invoker grants roles/cloudfunctions.invoker to allAuthenticatedUsers

#### Cloud Run service is publicly invokable

- STRIDE category: Spoofing
- Affected resources: `google_cloud_run_v2_service.api`, `google_cloud_run_v2_service_iam_member.public_invoker`
- Trust boundary: `internet-to-service:internet->google_cloud_run_v2_service.api`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +0, lateral_movement +0, blast_radius +1, final_score 3 => medium
- Rationale: google_cloud_run_v2_service.api allows public ingress and grants Cloud Run invoke permission to public GCP principals. Unauthenticated internet clients can reach the service entry point without an organization-owned identity boundary.
- Recommended mitigation: Remove `allUsers` and `allAuthenticatedUsers` from Cloud Run invoker bindings unless anonymous access is intentional, and front public services with authentication, IAP, API Gateway, or a controlled edge policy.
- Evidence:
  - public invoker bindings: source=google_cloud_run_v2_service_iam_member.public_invoker; role=roles/run.invoker; member=allUsers
  - public access reasons: google_cloud_run_v2_service_iam_member.public_invoker grants roles/run.invoker to allUsers
  - public exposure reasons: google_cloud_run_v2_service_iam_member.public_invoker grants roles/run.invoker to allUsers

#### Cloud SQL automated backups are disabled

- STRIDE category: Denial of Service
- Affected resources: `google_sql_database_instance.app`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 3 => medium
- Rationale: google_sql_database_instance.app does not have Cloud SQL automated backups enabled. A destructive change, operator error, or data corruption event would have fewer managed recovery points.
- Recommended mitigation: Enable automated backups for Cloud SQL instances, configure retention appropriate to the workload, and enable point-in-time recovery where supported.
- Evidence:
  - backup posture: backup_configuration.enabled is false; point_in_time_recovery_enabled is false; engine is POSTGRES_15

#### Cloud SQL deletion protection is disabled

- STRIDE category: Denial of Service
- Affected resources: `google_sql_database_instance.app`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 3 => medium
- Rationale: google_sql_database_instance.app has Cloud SQL deletion protection disabled. Accidental or unauthorized infrastructure changes could destroy the managed database instance without this provider-level guardrail.
- Recommended mitigation: Enable Cloud SQL deletion protection for persistent environments and require explicit review before disabling it during planned database retirement.
- Evidence:
  - lifecycle posture: deletion_protection is false

#### Cloud SQL instance uses zonal availability

- STRIDE category: Denial of Service
- Affected resources: `google_sql_database_instance.app`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 3 => medium
- Rationale: google_sql_database_instance.app uses zonal Cloud SQL availability. A zonal failure or maintenance disruption can leave the database unavailable longer than a regional high-availability deployment.
- Recommended mitigation: Use `REGIONAL` availability for production Cloud SQL instances that require higher availability, then validate application failover behavior and recovery objectives.
- Evidence:
  - availability posture: availability_type=ZONAL; engine=POSTGRES_15

#### Cloud SQL public IPv4 is enabled without private network access

- STRIDE category: Information Disclosure
- Affected resources: `google_sql_database_instance.app`
- Trust boundary: `internet-to-service:internet->google_sql_database_instance.app`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +2, lateral_movement +1, blast_radius +0, final_score 5 => medium
- Rationale: google_sql_database_instance.app has Cloud SQL public IPv4 enabled without a private network attachment. That keeps database client access on a public endpoint instead of an internal VPC path.
- Recommended mitigation: Disable public IPv4 where possible, attach the instance to a private network, and route clients through private IP, the Cloud SQL Auth Proxy, or tightly controlled connectivity paths.
- Evidence:
  - network posture: ipv4_enabled is true; private_network is unset; authorized_networks configured: 1
  - public access reasons: Cloud SQL public IPv4 access is enabled

#### Cloud SQL public client access does not require SSL

- STRIDE category: Information Disclosure
- Affected resources: `google_sql_database_instance.app`
- Trust boundary: `internet-to-service:internet->google_sql_database_instance.app`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +2, lateral_movement +1, blast_radius +0, final_score 5 => medium
- Rationale: google_sql_database_instance.app allows Cloud SQL public IPv4 client access without requiring encrypted client connections. Credentials and database traffic should not depend on client-side optional TLS behavior.
- Recommended mitigation: Require encrypted Cloud SQL client connections with `require_ssl` or an enforcing `ssl_mode`, and prefer private IP or the Cloud SQL Auth Proxy for application connectivity.
- Evidence:
  - ssl posture: require_ssl is false; ssl_mode is unset; ipv4_enabled is true

#### GCP compute instance disables OS Login

- STRIDE category: Elevation of Privilege
- Affected resources: `google_compute_instance.web`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +2, privilege_breadth +1, data_sensitivity +0, lateral_movement +1, blast_radius +1, final_score 5 => medium
- Rationale: google_compute_instance.web explicitly disables OS Login. SSH access can therefore fall back to instance or project metadata keys instead of centralized IAM-backed login and audit controls.
- Recommended mitigation: Enable OS Login on GCE instances and manage SSH access through IAM roles, two-factor enforcement, and centralized audit logs instead of metadata SSH keys.
- Evidence:
  - os login posture: metadata.enable-oslogin is false
  - public exposure reasons: compute instance has an external access config and matching firewall rules allow internet ingress

#### GCP project IAM binding grants access to public principals

- STRIDE category: Elevation of Privilege
- Affected resources: `google_project_iam_member.public_owner`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +2, privilege_breadth +1, data_sensitivity +0, lateral_movement +1, blast_radius +1, final_score 5 => medium
- Rationale: google_project_iam_member.public_owner grants `roles/owner` to `allUsers` at project scope. Public or broadly authenticated principals can cross into the control plane without an organization-owned identity boundary.
- Recommended mitigation: Remove `allUsers` and `allAuthenticatedUsers` from project-level IAM bindings, grant access to specific groups or service accounts, and scope permissions to the smallest project or resource needed.
- Evidence:
  - iam binding: member=allUsers; role=roles/owner

#### GCP service account user-managed key lacks rotation hygiene

- STRIDE category: Spoofing
- Affected resources: `google_service_account.web`, `google_service_account_key.web`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +1, data_sensitivity +0, lateral_movement +1, blast_radius +2, final_score 4 => medium
- Rationale: google_service_account_key.web creates a user-managed GCP service account key for `google_service_account.web`. User-managed service account keys are portable, long-lived credentials that can be copied outside GCP control, so they need explicit rotation controls or should be replaced with workload identity or impersonation flows.
- Recommended mitigation: Avoid user-managed service account keys where Workload Identity Federation, workload identity, or service-account impersonation can be used; when keys are unavoidable, keep lifetimes short, configure explicit rotation triggers, and store private material outside Terraform state.
- Evidence:
  - key context: source=google_service_account_key.web; service_account_reference=google_service_account.web.email; key_algorithm=KEY_ALG_RSA_2048; public_key_type=TYPE_X509_PEM_FILE
  - key risk: Terraform manages a user-created service-account key; validity window is 365 days and exceeds 180-day threshold; no Terraform keepers rotation trigger observed
  - validity window: valid_after=2026-01-01T00:00:00Z; valid_before=2027-01-01T00:00:00Z; validity_days=365
  - rotation control: no Terraform keepers rotation trigger observed

#### GCP subnetwork Flow Logs are not configured

- STRIDE category: Repudiation
- Affected resources: `google_compute_subnetwork.app`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +0, lateral_movement +2, blast_radius +1, final_score 3 => medium
- Rationale: google_compute_subnetwork.app does not configure VPC Flow Logs in this Terraform plan. Without subnetwork flow telemetry, network investigation, lateral-movement review, and egress analysis can lack packet-flow evidence for workloads attached to this subnet.
- Recommended mitigation: Enable VPC Flow Logs on subnetworks that host workloads, keep the flow log configuration in Terraform, and export or retain those logs according to investigation and monitoring requirements.
- Evidence:
  - subnetwork flow log posture: address=google_compute_subnetwork.app; type=google_compute_subnetwork; name=app; identifier=tfstride-app; flow_log_state=not_configured; network=google_compute_network.main.id; project=tfstride-demo

#### GCS bucket does not enforce Public Access Prevention

- STRIDE category: Information Disclosure
- Affected resources: `google_storage_bucket.logs`
- Trust boundary: `internet-to-service:internet->google_storage_bucket.logs`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 5 => medium
- Rationale: google_storage_bucket.logs does not enforce GCS Public Access Prevention. Public principals can still be introduced through bucket IAM unless an organization-level policy blocks them.
- Recommended mitigation: Set GCS Public Access Prevention to `enforced` on sensitive buckets and rely on explicit non-public identities or signed access patterns when objects must be shared.
- Evidence:
  - access control posture: public_access_prevention is unset
  - public exposure reasons: google_storage_bucket_iam_member.public_logs_reader grants roles/storage.objectViewer to allUsers

#### GCS bucket is publicly accessible

- STRIDE category: Information Disclosure
- Affected resources: `google_storage_bucket.logs`
- Trust boundary: `internet-to-service:internet->google_storage_bucket.logs`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 5 => medium
- Rationale: google_storage_bucket.logs is publicly reachable through GCS IAM grants. Public bucket access is a common source of unintended object disclosure.
- Recommended mitigation: Remove `allUsers` and `allAuthenticatedUsers` from bucket-level IAM grants, enforce GCS Public Access Prevention, and use signed URLs, CDN origins, or narrow identities when objects must be distributed.
- Evidence:
  - public exposure reasons: google_storage_bucket_iam_member.public_logs_reader grants roles/storage.objectViewer to allUsers

#### GCS sensitive bucket does not use customer-managed encryption

- STRIDE category: Information Disclosure
- Affected resources: `google_storage_bucket.logs`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 3 => medium
- Rationale: google_storage_bucket.logs relies on default GCS encryption rather than a customer-managed KMS key. Sensitive buckets lose key ownership, rotation, and separation-of-duties controls that a CMEK can provide.
- Recommended mitigation: Configure a Cloud KMS customer-managed key for sensitive GCS buckets, assign the GCS service agent only the key roles it needs, and manage key rotation separately from bucket IAM.
- Evidence:
  - encryption posture: default_kms_key_name is unset; customer_managed_encryption is false

#### GCS sensitive bucket retention policy is insufficient

- STRIDE category: Denial of Service
- Affected resources: `google_storage_bucket.logs`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 3 => medium
- Rationale: google_storage_bucket.logs does not have deterministic GCS retention posture that meets the minimum retention threshold and lock expectation. Retention policy and retention lock reduce destructive deletion or overwrite risk, but are distinct from soft-delete recovery controls.
- Recommended mitigation: Configure a GCS retention policy that meets recovery and compliance objectives, and lock the retention policy after operational validation. Treat retention lock as immutability posture, not as a replacement for object versioning or soft-delete recovery.
- Evidence:
  - retention policy issues: retention_policy is missing
  - retention policy posture: retention_policy.retention_period_state=missing; minimum_retention_period_days=7; minimum_retention_period_seconds=604800; retention_policy.is_locked is unset

#### GCS sensitive bucket versioning is disabled

- STRIDE category: Denial of Service
- Affected resources: `google_storage_bucket.logs`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 3 => medium
- Rationale: google_storage_bucket.logs stores sensitive GCS data without bucket versioning. Accidental overwrites, deletes, or destructive changes have fewer object-level recovery options.
- Recommended mitigation: Enable bucket versioning for sensitive GCS buckets and pair it with lifecycle retention rules that match recovery objectives and storage cost constraints.
- Evidence:
  - data protection posture: versioning.enabled is false; data_sensitivity is sensitive

#### GKE cluster does not enable Workload Identity

- STRIDE category: Elevation of Privilege
- Affected resources: `google_container_cluster.app`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +2, privilege_breadth +1, data_sensitivity +0, lateral_movement +1, blast_radius +1, final_score 5 => medium
- Rationale: google_container_cluster.app does not enable GKE Workload Identity. Pods are more likely to depend on node service-account credentials, which weakens workload-level identity boundaries and can expand blast radius after pod compromise.
- Recommended mitigation: Enable GKE Workload Identity, bind Kubernetes service accounts to narrow Google service accounts, and avoid relying on node service-account credentials for pod-level cloud API access.
- Evidence:
  - workload identity posture: workload_identity_enabled is false; workload_pool is unset

#### GKE cluster exposes a public control plane

- STRIDE category: Spoofing
- Affected resources: `google_container_cluster.app`
- Trust boundary: `internet-to-service:internet->google_container_cluster.app`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +0, lateral_movement +1, blast_radius +1, final_score 4 => medium
- Rationale: google_container_cluster.app exposes a public GKE control-plane endpoint. Public API server reachability increases dependence on IAM, Kubernetes RBAC, and authorized network configuration to protect cluster administration.
- Recommended mitigation: Use private GKE control-plane endpoints where possible, or restrict master authorized networks to narrow administrator CIDRs and enforce IAM plus Kubernetes RBAC for cluster administration.
- Evidence:
  - control plane endpoint: 35.4.5.6
  - public access reasons: GKE control plane endpoint is public
  - public exposure reasons: authorized network `anywhere` allows 0.0.0.0/0

#### GKE control plane allows broad authorized networks

- STRIDE category: Spoofing
- Affected resources: `google_container_cluster.app`
- Trust boundary: `internet-to-service:internet->google_container_cluster.app`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +0, lateral_movement +2, blast_radius +1, final_score 5 => medium
- Rationale: google_container_cluster.app exposes the GKE control plane without narrow master authorized networks. Internet-wide or unset CIDR controls leave the Kubernetes API server reachable from untrusted client networks.
- Recommended mitigation: Configure GKE master authorized networks with narrow trusted CIDRs, avoid internet-wide ranges, and prefer private control-plane access for administrative paths.
- Evidence:
  - authorized networks: anywhere (0.0.0.0/0)
  - configured authorized network count: 1
  - public exposure reasons: authorized network `anywhere` allows 0.0.0.0/0

#### GKE control-plane logging is incomplete

- STRIDE category: Repudiation
- Affected resources: `google_container_cluster.app`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +0, lateral_movement +2, blast_radius +1, final_score 3 => medium
- Rationale: google_container_cluster.app does not show deterministic GKE control-plane logging for key security components. Missing API server, scheduler, or controller manager logs can limit investigation of administrative and cluster-control activity.
- Recommended mitigation: Enable GKE control-plane logging for security-relevant components such as the API server, scheduler, and controller manager, and retain the logs in a monitored logging project.
- Evidence:
  - logging posture: control_plane_logging_state=not_configured; logging_service is not represented in planned values; logging_components are not represented in planned values; control-plane logging is not_configured

#### GKE network policy is not enabled

- STRIDE category: Tampering
- Affected resources: `google_container_cluster.app`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +0, lateral_movement +2, blast_radius +1, final_score 3 => medium
- Rationale: google_container_cluster.app does not deterministically enable GKE network policy. Without a pod network policy provider, Kubernetes workloads have weaker pod-level traffic isolation and lateral-movement controls.
- Recommended mitigation: Enable a supported GKE network policy provider and define namespace or workload policies that restrict pod-to-pod and pod-to-service traffic paths.
- Evidence:
  - network policy posture: network_policy_state=not_configured; network_policy_provider is not represented in planned values

#### GKE node metadata exposure is not hardened

- STRIDE category: Elevation of Privilege
- Affected resources: `google_container_node_pool.app`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +1, data_sensitivity +0, lateral_movement +1, blast_radius +1, final_score 3 => medium
- Rationale: google_container_node_pool.app allows legacy or broad node metadata exposure. Workloads on the node may be able to reach metadata credentials outside the intended GKE metadata server controls.
- Recommended mitigation: Disable legacy metadata endpoints, use GKE metadata server or Workload Identity controls, and prevent pods from reaching broad node credentials.
- Evidence:
  - node metadata posture: legacy metadata endpoints are enabled; metadata mode is GCE_METADATA

#### GKE secrets encryption is not configured

- STRIDE category: Information Disclosure
- Affected resources: `google_container_cluster.app`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 3 => medium
- Rationale: google_container_cluster.app does not show deterministic GKE application-layer secrets encryption with a Cloud KMS key. Kubernetes secrets may not have customer-controlled encryption key ownership represented in the Terraform plan.
- Recommended mitigation: Configure GKE application-layer secrets encryption with a Cloud KMS key where customer key ownership or stronger Kubernetes secret protection is required.
- Evidence:
  - secret encryption posture: secrets_encryption_state=disabled; database_encryption_state is not represented in planned values; database_encryption_key_name is not represented in planned values

#### Internet-exposed GCP compute instance permits broad ingress

- STRIDE category: Spoofing
- Affected resources: `google_compute_instance.web`, `google_compute_firewall.public_admin`
- Trust boundary: `internet-to-service:internet->google_compute_instance.web`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +0, lateral_movement +1, blast_radius +1, final_score 4 => medium
- Rationale: google_compute_instance.web has an external access config and matching GCP firewall rules allow administrative access or all ports from the public internet. That broad ingress raises the chance of unauthenticated probing and credential attacks.
- Recommended mitigation: Restrict GCP firewall source ranges and exposed ports, remove external IP access where possible, and use Identity-Aware Proxy, VPN, or a controlled bastion for administration.
- Evidence:
  - firewall rules: google_compute_firewall.public_admin ingress tcp 22 from 0.0.0.0/0; google_compute_firewall.public_admin ingress tcp 3389 from 0.0.0.0/0
  - network tags: web
  - internet ingress reasons: google_compute_firewall.public_admin ingress tcp 22 from 0.0.0.0/0; google_compute_firewall.public_admin ingress tcp 3389 from 0.0.0.0/0; google_compute_firewall.public_all ingress tcp unspecified ports from 0.0.0.0/0
  - public exposure reasons: compute instance has an external access config and matching firewall rules allow internet ingress

#### Pub/Sub subscription does not configure a dead-letter policy

- STRIDE category: Denial of Service
- Affected resources: `google_pubsub_subscription.events`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 3 => medium
- Rationale: google_pubsub_subscription.events does not configure a Pub/Sub dead-letter policy. Poison messages or repeated delivery failures can consume subscriber capacity and reduce recovery options for failed processing.
- Recommended mitigation: Configure a reviewed Pub/Sub dead-letter topic and delivery-attempt threshold for subscriptions where poison messages or repeated delivery failures could disrupt processing.
- Evidence:
  - target resource: address=google_pubsub_subscription.events; resource_type=google_pubsub_subscription
  - dead letter posture: dead_letter_policy_state=not_configured; dead_letter_topic=unset

#### Pub/Sub topic does not use customer-managed encryption

- STRIDE category: Information Disclosure
- Affected resources: `google_pubsub_topic.events`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 3 => medium
- Rationale: google_pubsub_topic.events relies on Google-managed Pub/Sub encryption rather than a customer-managed Cloud KMS key. Google-managed encryption still protects message data; this finding concerns key ownership, rotation, audit separation, and compliance posture.
- Recommended mitigation: Configure a customer-managed Cloud KMS key for sensitive Pub/Sub topics where key ownership, rotation, audit separation, or compliance requirements warrant it.
- Evidence:
  - target resource: address=google_pubsub_topic.events; resource_type=google_pubsub_topic
  - encryption ownership: cmek_state=not_configured; kms_key_name=unset

#### Secret Manager lifecycle posture is incomplete

- STRIDE category: Denial of Service
- Affected resources: `google_secret_manager_secret.api_key`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 3 => medium
- Rationale: google_secret_manager_secret.api_key does not show deterministic Secret Manager lifecycle posture for secret expiry or delayed version destruction. Expiry and version-destroy TTL controls reduce the lifetime of stale or accidentally destroyed secret material, but do not replace access review or rotation.
- Recommended mitigation: Configure Secret Manager `ttl` or `expire_time` where secret-level expiry is expected, and set `version_destroy_ttl` to a retention window that gives operators enough time to recover from accidental or malicious secret version destruction.
- Evidence:
  - target resource: address=google_secret_manager_secret.api_key; type=google_secret_manager_secret; identifier=projects/tfstride-demo/secrets/tfstride-api-key
  - lifecycle issues: secret has no ttl, expire_time, or version_destroy_ttl lifecycle guardrail; version_destroy_ttl is missing
  - lifecycle posture: ttl=unset; expire_time=unset; version_destroy_ttl=unset; minimum_version_destroy_ttl_days=7; minimum_version_destroy_ttl_seconds=604800

#### Secret Manager secret does not use customer-managed encryption

- STRIDE category: Information Disclosure
- Affected resources: `google_secret_manager_secret.api_key`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 3 => medium
- Rationale: google_secret_manager_secret.api_key relies on Google-managed Secret Manager encryption rather than a customer-managed Cloud KMS key. Google-managed encryption still applies; this finding concerns customer key ownership, rotation, audit separation, and compliance posture for sensitive secrets.
- Recommended mitigation: Configure Secret Manager replication with Cloud KMS customer-managed encryption for secrets that require customer key ownership, independent rotation, audit separation, or compliance controls.
- Evidence:
  - target resource: address=google_secret_manager_secret.api_key; type=google_secret_manager_secret; identifier=projects/tfstride-demo/secrets/tfstride-api-key
  - encryption ownership: customer_managed_encryption is false; secret_manager_replication_mode=automatic; secret_manager_kms_key_names is empty
  - replication posture: replication.mode=automatic

#### Sensitive GCP resource IAM binding allows broad or external access

- STRIDE category: Information Disclosure
- Affected resources: `google_kms_crypto_key.customer`, `google_kms_crypto_key_iam_member.partner_decrypter`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +1, data_sensitivity +2, lateral_movement +1, blast_radius +1, final_score 5 => medium
- Rationale: google_kms_crypto_key.customer grants `roles/cloudkms.cryptoKeyDecrypter` to `serviceAccount:decryptor@partner-project.iam.gserviceaccount.com` through GCP IAM. Public, broad-domain, or foreign-project principals can access sensitive secrets or cryptographic key operations outside the expected project trust boundary.
- Recommended mitigation: Grant Secret Manager and Cloud KMS IAM roles only to specific in-project service accounts or groups, remove public principals, and require explicit cross-project access reviews for partner identities.
- Evidence:
  - iam binding: source=google_kms_crypto_key_iam_member.partner_decrypter; role=roles/cloudkms.cryptoKeyDecrypter; member=serviceAccount:decryptor@partner-project.iam.gserviceaccount.com
  - trust scope: service account belongs to project `partner-project`, outside resource project `tfstride-demo`
  - resource policy sources: google_kms_crypto_key_iam_member.partner_decrypter

### Low

#### GKE Shielded Nodes is not enabled

- STRIDE category: Tampering
- Affected resources: `google_container_cluster.app`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +0, lateral_movement +0, blast_radius +1, final_score 1 => low
- Rationale: google_container_cluster.app does not show GKE Shielded Nodes enabled. Shielded Nodes add node integrity protections that reduce the impact of boot-level tampering and host compromise paths.
- Recommended mitigation: Enable GKE Shielded Nodes to add node integrity protections against boot-level tampering and host compromise paths.
- Evidence:
  - shielded nodes posture: shielded_nodes_state=unknown; shielded nodes setting is not represented in planned values

#### GKE legacy ABAC is enabled or unknown

- STRIDE category: Elevation of Privilege
- Affected resources: `google_container_cluster.app`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +0, lateral_movement +0, blast_radius +1, final_score 1 => low
- Rationale: google_container_cluster.app does not show legacy ABAC disabled. Legacy ABAC can bypass stronger IAM and Kubernetes RBAC expectations, and an unknown Terraform value should be reviewed before relying on RBAC-only authorization.
- Recommended mitigation: Disable legacy ABAC and rely on Kubernetes RBAC with centralized IAM-backed administration. Review unknown ABAC values before treating the cluster authorization posture as hardened.
- Evidence:
  - legacy abac posture: legacy_abac_state=unknown; enable_legacy_abac is not represented in planned values

## Limitations / Unsupported Resources

- GCP support covers a curated set of compute, serverless, data, IAM, Kubernetes, networking, audit, private-connectivity, messaging, registry, and key-management resources. Analysis is plan-local and does not model every provider resource, runtime drift, or every organization-level control; provider-specific positive observations remain more limited than finding coverage.
- The engine reasons over Terraform planned values only and does not validate runtime drift, CloudTrail evidence, or post-deploy control-plane activity.

Limits

Unsupported or intentionally scoped areas

  • GCP support covers a curated set of compute, serverless, data, IAM, Kubernetes, networking, audit, private-connectivity, messaging, registry, and key-management resources. Analysis is plan-local and does not model every provider resource, runtime drift, or every organization-level control; provider-specific positive observations remain more limited than finding coverage.
  • The engine reasons over Terraform planned values only and does not validate runtime drift, CloudTrail evidence, or post-deploy control-plane activity.