You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
chore(iac): low findings from the 2026-09-02 audit: CFN host param, GCP KMS key, dev CORS #324
Three low-severity Terraform and CloudFormation findings from the 2026-09-02 audit, grouped because each is a few-line change in the IaC tree and none is tracked elsewhere. Each item is independently actionable; keep the location and scenario with it if splitting any out.
CloudFormation WIF template makes the operator keep the issuer URL and its condition-key host in sync by hand (A13b-014)
Location: iac/federation/aws-target/cloudformation/template.yaml:20-28 (OIDCIssuerHost parameter), :265-267 (condition keys) at 3c0f8ac94048a2c36fce5ccddee54e6c4849a5cd
What: OIDCIssuerHost is a second free-text parameter whose own description says it must equal OIDCIssuerURL minus https:// and that keeping them in sync is the operator's job. Its two AllowedPatterns constrain shape only. The Terraform sibling derives the host in one line: iac/federation/aws-target/terraform/main.tf:22 (trimsuffix(trimprefix(var.oidc_issuer_url, "https://"), "/")).
Failure scenario: the two values disagree by a trailing slash or a tenant-ID typo. IAM never populates <host>:aud / <host>:sub for the incoming token, StringEquals fails, and every AssumeRoleWithWebIdentity is denied. It fails closed, but after the stack reports success, with no diagnostic naming the mismatch.
GCP OIDC signing key is explicitly unprotected where its AWS twin was given create_before_destroy (A13c-024)
Location: terraform/modules/compute/gcp/cloud-run/signing-key.tf:24-38 at 3c0f8ac94048a2c36fce5ccddee54e6c4849a5cd
What: google_kms_crypto_key.signing sets destroy_scheduled_duration = "86400s" with the comment "tests redeploy often" and an explicit lifecycle { prevent_destroy = false } (Terraform's default, so the line states rather than changes the posture). modules/compute/aws/lambda/signing-key.tf:19-27 carries create_before_destroy = true with a seven-line rationale citing fix(oidc): provision EC P-256 signing keys in Terraform to match ES256 code (follow-up to #882) cloud-commitments-cli#1480: replacing the OIDC signing key destroy-first breaks client-assertion JWT minting. The GCP key has neither mechanism.
Failure scenario: a ForceNew change on the key (purpose, version_template.algorithm, or the key ring's location via var.region) in a production project schedules the live signing key for destruction with a one-day window, and every federated target cloud rejects assertions until the new JWKS propagates.
Fix: make prevent_destroy and destroy_scheduled_duration module inputs so production gets the protective values and only test environments opt out, and add create_before_destroy = true to match the AWS twin.
A live Lambda Function URL hostname is hand-maintained in a tracked tfvars file (A13c-017)
Location: terraform/environments/aws/github-dev.tfvars:31-34 at 3c0f8ac94048a2c36fce5ccddee54e6c4849a5cd; terraform/.gitignore:12-16 ignores *.tfvars then re-admits !github-*.tfvars
What: the Function URL ID is server-assigned and only known after apply, so lambda_allowed_origins carries it pasted by hand, and the comment three lines above says to update it whenever dev is redeployed. The endpoint is a public URL, not a credential.
Failure scenario: a redeploy that reissues the URL silently invalidates the CORS allowlist. The failure surfaces as a browser CORS error, not as a Terraform diff.
Found by the 2026-09-02 codebase audit, findings A13b-014, A13c-024, A13c-017, reported by one reviewer and independently confirmed by a second. Full report: docs/audits/codebase-audit-2026-09-02.md.
Summary
Three low-severity Terraform and CloudFormation findings from the 2026-09-02 audit, grouped because each is a few-line change in the IaC tree and none is tracked elsewhere. Each item is independently actionable; keep the location and scenario with it if splitting any out.
CloudFormation WIF template makes the operator keep the issuer URL and its condition-key host in sync by hand (
A13b-014)iac/federation/aws-target/cloudformation/template.yaml:20-28(OIDCIssuerHostparameter),:265-267(condition keys) at 3c0f8ac94048a2c36fce5ccddee54e6c4849a5cdOIDCIssuerHostis a second free-text parameter whose own description says it must equalOIDCIssuerURLminushttps://and that keeping them in sync is the operator's job. Its twoAllowedPatterns constrain shape only. The Terraform sibling derives the host in one line:iac/federation/aws-target/terraform/main.tf:22(trimsuffix(trimprefix(var.oidc_issuer_url, "https://"), "/")).<host>:aud/<host>:subfor the incoming token,StringEqualsfails, and everyAssumeRoleWithWebIdentityis denied. It fails closed, but after the stack reports success, with no diagnostic naming the mismatch.OIDCIssuerHostand derive it as!Select [1, !Split ["https://", !Ref OIDCIssuerURL]]so one input cannot contradict the other.aws-cfn-deploy.sh.tmplpasses the parameter today (see chore(scripts): generate-federation-iac.go iacData has drifted out of sync with the templates it renders #153), so drop it from the parameter overrides in the same change.GCP OIDC signing key is explicitly unprotected where its AWS twin was given create_before_destroy (
A13c-024)terraform/modules/compute/gcp/cloud-run/signing-key.tf:24-38at 3c0f8ac94048a2c36fce5ccddee54e6c4849a5cdgoogle_kms_crypto_key.signingsetsdestroy_scheduled_duration = "86400s"with the comment "tests redeploy often" and an explicitlifecycle { prevent_destroy = false }(Terraform's default, so the line states rather than changes the posture).modules/compute/aws/lambda/signing-key.tf:19-27carriescreate_before_destroy = truewith a seven-line rationale citing fix(oidc): provision EC P-256 signing keys in Terraform to match ES256 code (follow-up to #882) cloud-commitments-cli#1480: replacing the OIDC signing key destroy-first breaks client-assertion JWT minting. The GCP key has neither mechanism.purpose,version_template.algorithm, or the key ring'slocationviavar.region) in a production project schedules the live signing key for destruction with a one-day window, and every federated target cloud rejects assertions until the new JWKS propagates.prevent_destroyanddestroy_scheduled_durationmodule inputs so production gets the protective values and only test environments opt out, and addcreate_before_destroy = trueto match the AWS twin.A live Lambda Function URL hostname is hand-maintained in a tracked tfvars file (
A13c-017)terraform/environments/aws/github-dev.tfvars:31-34at 3c0f8ac94048a2c36fce5ccddee54e6c4849a5cd;terraform/.gitignore:12-16ignores*.tfvarsthen re-admits!github-*.tfvarslambda_allowed_originscarries it pasted by hand, and the comment three lines above says to update it whenever dev is redeployed. The endpoint is a public URL, not a credential.TF_VAR_lambda_allowed_origins, reading the previous apply'sfunction_urloutput, instead of committing the host. sec(iac): flip dev/staging/prod to AWS_IAM + enable CloudFront OAC (runtime cut-over for #424) #16 (CloudFront cut-over) would replace this origin with a stable domain and make the item moot; fix here only if sec(iac): flip dev/staging/prod to AWS_IAM + enable CloudFront OAC (runtime cut-over for #424) #16 stays parked.Found by the 2026-09-02 codebase audit, findings
A13b-014,A13c-024,A13c-017, reported by one reviewer and independently confirmed by a second. Full report:docs/audits/codebase-audit-2026-09-02.md.