Summary
Step 4 of cudly configure-gcp grants the CUDly service account roles/compute.admin at project scope, and the prompt treats empty input as Run. The next steps mint a long-lived JSON key for that identity and upload it to AWS Secrets Manager. That role confers full control of Compute Engine, including deleting VMs, disks, images, firewall rules and networks, where CUDly needs to read usage and buy committed use discounts. The project's own IAM policy names this role as the anti-pattern to avoid.
Location
cmd/configure_gcp.go:686 at 3c0f8ac
Failure scenario
Step 4 of cudly configure-gcp grants the CUDly service account roles/compute.admin on the operator's project, then Step 5 mints a long-lived JSON key for it and Step 6 uploads that key to AWS Secrets Manager. compute.admin confers full control of every Compute Engine resource: creating and deleting VMs, disks, images, firewall rules and networks. CUDly needs to read usage and purchase committed use discounts. Anyone who obtains the stored key can delete the project's production infrastructure. The project's own IAM policy in CLAUDE.md names this exact role as the anti-pattern ("Prefer custom roles ... over broad predefined roles like roles/compute.admin"), and the prompt defaults to Run on empty input.
Evidence
member := fmt.Sprintf("serviceAccount:%s", saEmail)
role := "roles/compute.admin"
...
fmt.Printf("[R]un, [S]kip? (grants %s to %s on project %s via SDK) ", role, saEmail, projectID)
Suggested fix
Grant the narrowest predefined pair the CUD flow needs (roles/compute.viewer plus the commitment-purchase permissions) or provision a google_project_iam_custom_role holding only compute.commitments.* and the usage reads, matching the runtime-permissions rule in CLAUDE.md.
Found by the 2026-09-02 codebase audit, finding A10-018, reported by one reviewer and independently confirmed by a second. Full report: docs/audits/codebase-audit-2026-09-02.md.
Summary
Step 4 of
cudly configure-gcpgrants the CUDly service accountroles/compute.adminat project scope, and the prompt treats empty input as Run. The next steps mint a long-lived JSON key for that identity and upload it to AWS Secrets Manager. That role confers full control of Compute Engine, including deleting VMs, disks, images, firewall rules and networks, where CUDly needs to read usage and buy committed use discounts. The project's own IAM policy names this role as the anti-pattern to avoid.Location
cmd/configure_gcp.go:686at 3c0f8acFailure scenario
Step 4 of
cudly configure-gcpgrants the CUDly service accountroles/compute.adminon the operator's project, then Step 5 mints a long-lived JSON key for it and Step 6 uploads that key to AWS Secrets Manager.compute.adminconfers full control of every Compute Engine resource: creating and deleting VMs, disks, images, firewall rules and networks. CUDly needs to read usage and purchase committed use discounts. Anyone who obtains the stored key can delete the project's production infrastructure. The project's own IAM policy in CLAUDE.md names this exact role as the anti-pattern ("Prefer custom roles ... over broad predefined roles likeroles/compute.admin"), and the prompt defaults to Run on empty input.Evidence
Suggested fix
Grant the narrowest predefined pair the CUD flow needs (
roles/compute.viewerplus the commitment-purchase permissions) or provision agoogle_project_iam_custom_roleholding onlycompute.commitments.*and the usage reads, matching the runtime-permissions rule in CLAUDE.md.Found by the 2026-09-02 codebase audit, finding
A10-018, reported by one reviewer and independently confirmed by a second. Full report:docs/audits/codebase-audit-2026-09-02.md.