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(ci): delete stale azure-/gcp- junk GitHub environments; root cause identified and already fixed #147
Cross-links LeanerCloud/cloud-commitments-cli#1660, which flagged these two junk environments and listed "identify which workflow created them" as an open action item. This issue closes that identification and requests the cleanup.
Root cause, identified
gh api repos/LeanerCloud/CUDly/environments shows two malformed environments: azure- and gcp- (trailing hyphen, empty suffix), both created 2026-03-25T10:46:44Z, zero protection rules, zero deployment branch policy.
gh api "repos/LeanerCloud/CUDly/deployments?environment=azure-" (and ?environment=gcp-) shows exactly 3 deployment records each, all against the same 3 commits, all on ref feat/multicloud-web-frontend, all within an 8-minute window on 2026-03-25T10:46-10:54Z:
cb386249e feat(ci-cd): switch deploy workflows to OIDC keyless auth
206f2f7d0
7cebce7c1 feat(ci-cd): wire remote state backend config for deploy workflows
At cb386249e, both .github/workflows/deploy-azure.yml and deploy-gcp.yml had:
on:
push:
branches: [main, feat/multicloud-web-frontend]workflow_dispatch:
inputs:
environment: ...jobs:
deploy:
environment:
name: azure-${{ inputs.environment }} # (gcp-${{ inputs.environment }} in deploy-gcp.yml)
inputs.environment is only populated on workflow_dispatch/workflow_call; on the push trigger (which is what fired for these 3 commits, landing on feat/multicloud-web-frontend) it resolves to empty, so the environment name rendered as the literal string azure- / gcp-. GitHub auto-created both bare, with no protection rules, exactly as observed.
Already fixed on current main, confirmed by inspection
Commits fecd8c637 (ci(azure): standardize deploy pipeline for consistency) and 626d96651 (ci(gcp): standardize deploy pipeline for consistency) replaced the direct inputs.environment interpolation with a prepare job whose steps.set-env step resolves the environment via an explicit if/elif/else (release -> a fixed value, workflow_dispatch/workflow_call -> the input, else -> a fixed fallback), so it can never be empty. A later refactor removed the job-level environment: binding from both files entirely: checked current main (python3 -c "import yaml; ..." over both files' jobs.*.environment keys) and neither deploy-azure.yml nor deploy-gcp.yml binds any job to a GitHub environment today.
No further deployment records exist against azure-/gcp- after 2026-03-25T10:53:59Z (over 4 months as of this writing), consistent with the vulnerable code path being dead.
Checked while auditing LeanerCloud/cloud-commitments-cli#1648's PR (LeanerCloud/cloud-commitments-cli#1683, extending the AWS cudly_deploy trust policy allowlist): no job that assumes cudly_deploy can produce or has ever produced an azure-/gcp- subject. deploy-azure.yml authenticates via azure/login (Azure SP), deploy-gcp.yml via google-github-actions/auth (GCP WIF); neither calls aws-actions/configure-aws-credentials or assumes any AWS role. Wrong cloud, wrong action, wrong role, structurally disjoint from the AWS allowlist regardless of the environment name's shape.
Ask
Delete the azure- and gcp- environments via Settings -> Environments (or the API) now that the creating code path is confirmed dead and no other workflow references them.
General hygiene worth carrying forward, already noted in LeanerCloud/cloud-commitments-cli#1660's fix direction AWS + Azure: add read-only sanity checks + AWS RI exchange cloud-commitments-cli#3: an environment: name should never be allowed to render empty. PR LeanerCloud/cloud-commitments-cli#1657 already validates this for deploy-aws-lambda.yml's environment input; the same pattern doesn't currently need re-applying to deploy-azure.yml/deploy-gcp.yml since they no longer interpolate into an environment: binding at all, but worth keeping in mind for any future workflow that does.
Related: LeanerCloud/cloud-commitments-cli#1660 (owns "environments need protection rules and shouldn't exist bare"; this issue supplies the root-cause identification LeanerCloud/cloud-commitments-cli#1660 was waiting on), LeanerCloud/cloud-commitments-cli#1648 / PR LeanerCloud/cloud-commitments-cli#1683 (AWS allowlist, confirmed unaffected by this).
Cross-links LeanerCloud/cloud-commitments-cli#1660, which flagged these two junk environments and listed "identify which workflow created them" as an open action item. This issue closes that identification and requests the cleanup.
Root cause, identified
gh api repos/LeanerCloud/CUDly/environmentsshows two malformed environments:azure-andgcp-(trailing hyphen, empty suffix), both created2026-03-25T10:46:44Z, zero protection rules, zero deployment branch policy.gh api "repos/LeanerCloud/CUDly/deployments?environment=azure-"(and?environment=gcp-) shows exactly 3 deployment records each, all against the same 3 commits, all on reffeat/multicloud-web-frontend, all within an 8-minute window on 2026-03-25T10:46-10:54Z:At
cb386249e, both.github/workflows/deploy-azure.ymlanddeploy-gcp.ymlhad:inputs.environmentis only populated onworkflow_dispatch/workflow_call; on thepushtrigger (which is what fired for these 3 commits, landing onfeat/multicloud-web-frontend) it resolves to empty, so the environment name rendered as the literal stringazure-/gcp-. GitHub auto-created both bare, with no protection rules, exactly as observed.Already fixed on current
main, confirmed by inspectionCommits
fecd8c637(ci(azure): standardize deploy pipeline for consistency) and626d96651(ci(gcp): standardize deploy pipeline for consistency) replaced the directinputs.environmentinterpolation with apreparejob whosesteps.set-envstep resolves the environment via an explicitif/elif/else(release -> a fixed value, workflow_dispatch/workflow_call -> the input, else -> a fixed fallback), so it can never be empty. A later refactor removed the job-levelenvironment:binding from both files entirely: checked currentmain(python3 -c "import yaml; ..."over both files'jobs.*.environmentkeys) and neitherdeploy-azure.ymlnordeploy-gcp.ymlbinds any job to a GitHub environment today.No further deployment records exist against
azure-/gcp-after2026-03-25T10:53:59Z(over 4 months as of this writing), consistent with the vulnerable code path being dead.Not a live vulnerability, not a merge blocker for LeanerCloud/cloud-commitments-cli#1683
Checked while auditing LeanerCloud/cloud-commitments-cli#1648's PR (LeanerCloud/cloud-commitments-cli#1683, extending the AWS
cudly_deploytrust policy allowlist): no job that assumescudly_deploycan produce or has ever produced anazure-/gcp-subject.deploy-azure.ymlauthenticates viaazure/login(Azure SP),deploy-gcp.ymlviagoogle-github-actions/auth(GCP WIF); neither callsaws-actions/configure-aws-credentialsor assumes any AWS role. Wrong cloud, wrong action, wrong role, structurally disjoint from the AWS allowlist regardless of the environment name's shape.Ask
azure-andgcp-environments via Settings -> Environments (or the API) now that the creating code path is confirmed dead and no other workflow references them.environment:name should never be allowed to render empty.PR LeanerCloud/cloud-commitments-cli#1657already validates this fordeploy-aws-lambda.yml's environment input; the same pattern doesn't currently need re-applying todeploy-azure.yml/deploy-gcp.ymlsince they no longer interpolate into anenvironment:binding at all, but worth keeping in mind for any future workflow that does.Related: LeanerCloud/cloud-commitments-cli#1660 (owns "environments need protection rules and shouldn't exist bare"; this issue supplies the root-cause identification LeanerCloud/cloud-commitments-cli#1660 was waiting on), LeanerCloud/cloud-commitments-cli#1648 / PR LeanerCloud/cloud-commitments-cli#1683 (AWS allowlist, confirmed unaffected by this).