Skip to content

sec(ci): cleanup-staging.yml still force-deletes ECR repos by prefix, the shape #1592 rejected #1820

Description

@cristim

Deferred from #1815 (which closes #1592). #1815 hardened 1 of the 3 aws 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:

file sites
cleanup-staging.yml 2
destroy-fargate-dev.yml 1 (hardened by #1815)

What

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.

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions