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
sec(ci): cleanup-staging.yml still force-deletes ECR repos by prefix, the shape #1592 rejected #1820
Deferred from #1815 (which closes #1592). #1815 hardened 1 of the 3aws ecr delete-repository --force sites in .github/workflows/; the other two are unchanged and carry the same defect class #1592 was filed for.
Enumerated by predicate across .github/workflows/*.yml (rg -c 'delete-repository'), not sampled:
Both cleanup-staging.yml sites select repositories with a case "$REPO" in cudly-staging*) prefix allow-list and swallow failures with 2>/dev/null || echo.
Why it matters
A prefix allow-list is the exact shape #1592 argued against. cudly-staging* also selects cudly-staging-prod-mirror, cudly-staging-1a2b3c4d-backup, and any other repository an operator names with that prefix, and the workflow force-deletes every image in them. Swallowing the failure means a partial deletion reports success.
The state-lock half of #1592 was already fixed by #1806; this is the remaining name-matching half in the sibling workflow. The recurrence mode for this class is precisely "the guard landed in one workflow and not the sibling", which is how #1592 arose after cleanup-staging.yml was hardened in #1235/#1330.
Fix direction
Reuse scripts/select-ecr-repos-to-delete.sh, added by #1815. It compares by exact equality against a name read from terraform output, exits 2 rather than degrading on an empty or whitespace-bearing name, and has a self-test asserting both directions. The staging workflow needs the same treatment: resolve the owned repository name from the state being torn down and pipe the account listing through the selector.
Note the selector's stdin contract when adopting it: see the trailing-newline handling that #1815 addresses.
Verification bar
Assert both directions, as the existing selector suite does: a substring or prefix near-miss is refused, AND the legitimate owned repository is still selected. A selector that returns nothing passes a refusal-only suite while silently leaving the repository behind.
Activity
sec(ci): select ECR repos to destroy by exact name, not substring (#1592
sec(ci): delete only the ECR repo each staging state owns (#1820)
test(ci): match ECR delete invocations, not prose, in the wiring sweep (
ci: scope the ecr-delete-selection job to contents: read (#1820)
refactor(ci): delete the owned ECR repo from one script all three des…
sec(ci): delete only the ECR repo each staging state owns (#1848)
fix(ci): sweep every script for unguarded destroy calls, not two name…
sec(ci): unprotect only the RDS instance each state owns before destr…
sec(ci): select ECR repos to destroy by exact name, not substring (#1592
sec(ci): delete only the ECR repo each staging state owns (#1848)
sec(ci): unprotect only the RDS instance each state owns before destr…