Commit f5e0941
authored
feat(cicd_rules): :known_fake_action_sha rule — block partial-prefix-corruption fakes (#397)
## Summary
Adds a new `Hypatia.Rules.CicdRules` entry that flags GitHub Action pins
where the SHA is fabricated. Complement to the existing
`:unpinned_action` rule.
## Problem
Estate audit on 2026-05-30 found **67 fake action SHA pairs across ~50
repos** (11% fabrication rate across 372 unique pins). Verified via `gh
api repos/<org>/<action>/commits/<sha>` returning 422.
**Universal pattern: partial-prefix corruption.** The first 8-20 hex
chars match a real release's SHA; the suffix is fabricated. Examples:
| Fake | Real | Real version |
|---|---|---|
| `7ab2955eb728f5440978d`**7b4f723a50dea1f3608** |
`7ab2955eb728f5440978d`**5824358023be3a2802d** | setup-zig v2.2.0 |
| `49933ea5288caeca8642`**195f2b846b8bbe245a93** |
`49933ea5288caeca8642`**d1e84afbd3f7d6820020** | setup-node v4.4.0 |
| `909cc5acb0`**135c37a79510dd77767e217930de55** |
`909cc5acb0`**fdd60627fb858598759246509fa755** | setup-deno v2.0.2 |
Almost certainly a single AI-hallucination event that propagated across
the estate via copy-customise of templates. The fakes slip past visual
review because of the matching prefix.
## What this rule does
Adds `:known_fake_action_sha` to `@blocked_patterns` enumerating the 25
known fakes from the audit. Caught at scan time; blocks new code from
re-introducing them. Reason field links to the substitution map in
`project_estate_fake_action_sha_punch_list_2026_05_30` memory entry.
`applies_to: [\"*.yml\", \"*.yaml\"]` to scope to workflow files.
## Tested inline (transcript)
```
✓ expect=true got=true :: known fake setup-beam
✓ expect=true got=true :: known fake upload-artifact (partial-prefix)
✓ expect=false got=false :: REAL upload-artifact v4.6.2 (no false-positive)
✓ expect=false got=false :: REAL setup-node v4.4.0 (no false-positive)
✓ expect=true got=true :: fake setup-node (partial-prefix corruption)
✓ expect=true got=true :: fake codeql
✓ expect=false got=false :: REAL checkout v4 (no false-positive)
```
## Out of scope
For proactive detection of FUTURE fakes (beyond the static 25-entry
list), a `mix hypatia.verify_action_shas` task is the right shape —
needs network access to `gh api`, can't be a static-regex rule.
Documented as a follow-up in the punch-list memory.
## Provenance
Discovered while wiring `hyperpolymath/snifs#30` build-mode CI gate. The
static-rule design intent was previously captured in
`feedback_verify_action_sha_pins` memory:
> Consider adding a complementary rule that VERIFIES SHA pins resolve
upstream — would have caught all four fakes above.
This PR ships the static-list version of that idea.
## Test plan
- [ ] Rule compiles + registers (verified locally)
- [ ] No false-positives on real action SHAs in current estate workflows
- [ ] When scanning the 50 repos still carrying these fakes, the rule
flags them
- [ ] After round-2 sweep (admin-merge style, in flight as PID 607915)
completes, the rule's positives should drop to zero estate-wide1 parent 15af96a commit f5e0941
1 file changed
Lines changed: 29 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
549 | 549 | | |
550 | 550 | | |
551 | 551 | | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
552 | 581 | | |
553 | 582 | | |
554 | 583 | | |
| |||
0 commit comments