Repository navigation
sec(ci): check-gcp-secret-scope misses google_project_iam_policy and unindented resource blocks #150
Description
Follow-up to LeanerCloud/cloud-commitments-cli#1614 / PR LeanerCloud/cloud-commitments-cli#1682, which added scripts/check-gcp-secret-scope.sh. Sibling of #149 (the locals / for_each blind spot). Neither shape exists in the repo today, so this is hardening, not a live exposure.
1. google_project_iam_policy + data "google_iam_policy"
The authoritative-policy shape binds roles like this:
data "google_iam_policy" "admin" {
binding {
role = "roles/secretmanager.admin"
members = ["serviceAccount:..."]
}
}
resource "google_project_iam_policy" "project" {
project = var.project_id
policy_data = data.google_iam_policy.admin.policy_data
}Note that simply adding _policy to the guard's resource-type list would not fix this: the role literal lives in the data block, which is not a tracked resource block, while the resource block that applies it project-wide contains no role at all. Catching this needs the two blocks correlated through policy_data.
This shape is also the most dangerous of the three, because google_project_iam_policy is authoritative: it replaces the project's entire IAM policy rather than adding to it.
2. Unindented resource bypass
The scanner detects a block close with /^}/ and a block open with ^resource. A resource whose body lines start at column 0 ends the block early, so a role literal after that point is not attributed to the block.
Inside terraform/ this is mitigated by terraform fmt -check -recursive terraform/ (.github/workflows/ci.yml:254), which enforces the indentation the scanner assumes. It is not mitigated anywhere else, and PR LeanerCloud/cloud-commitments-cli#1682 extends the guard's scan root to iac/, which has no equivalent fmt gate. So the assumption the scanner relies on is only enforced for part of what it now scans.
Suggested fix
Neither shape exists in the repo, so the smallest remedy that closes both is to make the guard refuse what it cannot analyse rather than teach it to analyse a shape nobody uses. The guard already does exactly this for .tf.json, which it exits 2 on rather than reporting clean.
google_project_iam_policy/data "google_iam_policy": exit 2, with a message saying the guard cannot analyse the authoritative-policy shape and pointing here. Nopolicy_datacorrelation to build, no binding-shape fixtures to maintain, and the first person to add one of these blocks is routed to this issue instead of getting a false green. Correlating the two blocks is the right work when the shape arrives.- Unindented resource bypass: extend the existing
terraform fmt -check -recursivestep (.github/workflows/ci.yml:254) to coveriac/as well asterraform/, so the indentation the scanner assumes is enforced across everything it now scans. One line, and it has independent value.
Acceptance
- A fixture containing
google_project_iam_policyexits 2 (not 0). terraform fmt -checkcovers every root in the guard'sSCAN_ROOTS, andiac/is formatted so the new step passes.- The LIMITATIONS header records that the authoritative-policy shape is rejected rather than unanalysed.
Remedy simplified (2026-08-03): correlating data "google_iam_policy" with google_project_iam_policy through policy_data, and the fixtures for it, were dropped in favour of failing closed on the shape, matching the guard's existing .tf.json handling. Neither shape exists in the tree, so building analysis for them now is work against a hypothetical. The HCL-parser rewrite is dropped for the same reason as in #149; the fmt gate covers the indentation assumption at a fraction of the cost.
Activity
sec(ci): make the Secret Manager guard cover iac/ and stop overclaiming
sec(ci): make the Secret Manager guard cover iac/ and stop overclaiming
sec(iac/gcp): scope cleanup-function SA to the one secret it reads (#…
sec(iac/gcp): scope cleanup-function SA to the one secret it reads (#…
IAmJSD commentedon Oct 20, 2026
Claiming: working on this
sec(ci): refuse authoritative GCP IAM policies in the secret scope gu…
sec(ci): allowlist the roles a per-secret Secret Manager grant may ca…