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): RDS deletion protection is stripped by identifier prefix at 3 sites, hardening none #1821
Deferred from #1815. Surfaced by the adversarial review of that PR, in the same job it hardened.
Enumerated by predicate across .github/workflows/*.yml (rg -n 'starts_with\(DBInstanceIdentifier'), not sampled. 3 sites, 0 hardened:
file
line
prefix
destroy-fargate-dev.yml
158
cudly-dev
cleanup-staging.yml
164
cudly-staging
cleanup-staging.yml
249
cudly-staging
What
Each site queries RDS with DBInstances[?starts_with(DBInstanceIdentifier,'<prefix>')] and strips deletion protection from every match, with failures swallowed (2>/dev/null || true).
Why it matters
This is the same over-matching class as #1592, on a different resource, and it weakens a delete-guard rather than merely selecting a delete target. starts_with(…,'cudly-dev') matches cudly-dev-prod-mirror, cudly-dev-1a2b3c4d-replica, and any operator-named instance sharing the prefix. Deletion protection is the last line of defence on a database; removing it from an instance the workflow does not own leaves that instance exposed to the next destroy that does match it.
destroy-fargate-dev.yml:158 is the notable one: it sits immediately after the ECR step #1815 hardened, in the same job, so the file now selects ECR repositories by exact equality and RDS instances by prefix.
Swallowing the failure with || true means a partial or failed strip also reports success.
Fix direction
Resolve the owned instance identifier from the state being torn down (terraform output), the way #1815 does for ECR, and compare by exact equality. If more than one instance is legitimately owned, enumerate them from state rather than pattern-matching the account.
Do not swallow the failure: if deletion protection cannot be removed from an instance the state owns, that should fail loudly rather than letting terraform destroy hit a confusing downstream error.
Verification bar
Both directions: a prefix near-miss is refused, AND the legitimately owned instance is still selected. A selector that returns nothing passes a refusal-only test while leaving the destroy broken.
Activity
sec(ci): select ECR repos to destroy by exact name, not substring (#1592
fix(ci): tell a state predating the RDS output apart from an empty one
fix(ci): sweep every script for unguarded destroy calls, not two name…
sec(ci): select ECR repos to destroy by exact name, not substring (#1592