From 5886da1d3538cc755931d7a62811fbc34372cad9 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Oct 2026 00:56:54 +0000 Subject: [PATCH] ci(hypatia): retire the cured invalid_actions_lock ack (#963) The .hypatia-baseline.json entry for invalid_actions_lock (rule_module [workflow_audit, workflow_hardening], file_pattern `**actions.lock`, tracking #963, expires 2026-12-22) acknowledged asana/push-signed-commits@d615... declaring the floating transitive actions/setup-python@v2 in .github/workflows/actions.lock. Its exit criterion "we replace the action" is met: - #1233 replaced the Asana action in .github/actions/signed-push/ with push-verified.sh. - #1238 removed both the asana/push-signed-commits and actions/setup-python@v2 records from actions.lock. Every lock key and every nested `uses:` ref is now a 40-hex SHA. Evidence the rule no longer fires: the Hypatia scan on main at 7d2041a (run 38484072239, scanner 51ab6496) reports 59 findings, none of type invalid_actions_lock and none naming actions.lock. findings_kept is empty, and the ack matched nothing in findings_suppressed. While it stood, `**actions.lock` would have muted ANY new invalid_actions_lock in the repo until 2026-12-22. Removing it shrinks the ledger, which check-exemption-ratchet.sh permits. No other entry changes. scripts/tests/apply-baseline-test.sh pinned the shipped ledger to hold exactly one such ack, so that section is inverted. It now asserts the ledger holds none and that both emission paths (workflow_audit `actions.lock`, workflow_hardening `.github/workflows/actions.lock`) reach the gate. The fixture-based list-valued rule_module tests are unchanged. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01TbbnKqskQA5mj5gfMniPzi --- .hypatia-baseline.json | 12 ------- scripts/tests/apply-baseline-test.sh | 49 +++++++++++----------------- 2 files changed, 19 insertions(+), 42 deletions(-) diff --git a/.hypatia-baseline.json b/.hypatia-baseline.json index 6e016893f..7f89fa5ab 100644 --- a/.hypatia-baseline.json +++ b/.hypatia-baseline.json @@ -1508,18 +1508,6 @@ "expires_at": "2026-12-22", "tracking_issue": "hyperpolymath/standards#937" }, - { - "severity": "high", - "rule_module": [ - "workflow_audit", - "workflow_hardening" - ], - "type": "invalid_actions_lock", - "file_pattern": "**actions.lock", - "note": "TRIAGED (round-2 fix-forward 2026-09-22; collapsed 2026-09-22 per #966): Hypatia emits invalid_actions_lock from TWO rule modules for ONE defect -- workflow_audit/parse_actions_lock (file `actions.lock`) and WH004 standalone (workflow_hardening, full path `.github/workflows/actions.lock`). Both verified by running the real scanner locally. The defect: asana/push-signed-commits@d615 (immutable pin, ref v1.3) declares transitive actions/setup-python@v2, which floats upstream and can never be a lock key. gh-actions-lock v0.1.6 verify says valid:true on the same file; Hypatia is stricter than the authoritative tool. Exposure is upstream float only. Exit: Asana pins setup-python, we replace the action, or Hypatia downgrades float-transitives. #947 deleted the metadata to silence the scanner; round 2 restored it verbatim and acked honestly. Tracking moved from #951 to #963 on 2026-09-22: #951 was closed COMPLETED with zero comments while the defect is demonstrably live (actions.lock:210 still declares the floating transitive under the asana pin, and setup-python is never a top-level lock key), because #963 superseded it. An acknowledgement expiring 2026-12-22 against a CLOSED issue has nobody owning its exit criteria -- the ack keeps working and the cure stops being anyone job. This was two entries until list-valued rule_module landed (#971) -- two entries meant two expiry dates for one decision, which is how a half-expired acknowledgement silently reopens a gate. DELIBERATE SCOPE CHANGE, recorded because it is a widening and not a refactor: the workflow_hardening half previously matched the exact path `.github/workflows/actions.lock`, and one entry carries one matcher, so it now matches `**actions.lock` -- the breadth the workflow_audit half already had at the same severity and type. Measured consequence: a workflow_hardening invalid_actions_lock at e.g. `vendor/actions.lock` was KEPT before and is SUPPRESSED now. Accepted because both halves are the same defect with the same exit criteria; if a second actions.lock is ever vendored, narrow this entry rather than trusting it.", - "expires_at": "2026-12-22", - "tracking_issue": "hyperpolymath/standards#963" - }, { "severity": "warn", "rule_module": "research_extensions", diff --git a/scripts/tests/apply-baseline-test.sh b/scripts/tests/apply-baseline-test.sh index e94ec6fbc..10cc079e7 100755 --- a/scripts/tests/apply-baseline-test.sh +++ b/scripts/tests/apply-baseline-test.sh @@ -284,55 +284,44 @@ else fi # --- The SHIPPED ledger, not a fixture ------------------------------------- -# #966: hypatia emits invalid_actions_lock from BOTH workflow_audit and -# workflow_hardening for one defect. It was acked twice, which meant two -# expiry dates for one decision — the shape in which a half-expired ack -# silently reopens a gate. #971 made rule_module list-valued; this collapses -# the pair into one entry. These assertions run against the real -# .hypatia-baseline.json so that splitting it back, or narrowing the matcher, -# reds this suite instead of quietly un-suppressing a live finding. +# #963: the shipped ledger used to carry ONE invalid_actions_lock ack naming +# both workflow_audit and workflow_hardening (`**actions.lock`), for +# asana/push-signed-commits' floating transitive actions/setup-python@v2. +# #1233 replaced the action and #1238 dropped both records from actions.lock, +# so the ack was removed. While it stood, `**actions.lock` muted ANY new +# invalid_actions_lock until 2026-12-22. These assertions run against the real +# .hypatia-baseline.json so that restoring the ack reds this suite instead of +# quietly muting the next lock defect. SHIPPED="$SCRIPT_DIR/../../.hypatia-baseline.json" if [ ! -f "$SHIPPED" ]; then echo "FAIL: shipped baseline not found at $SHIPPED" fail=$((fail + 1)) else - # Exactly one entry, and it must name BOTH modules. - got=$(jq -r '[.[] | select(.type == "invalid_actions_lock")] as $e - | "\($e | length),\($e[0].rule_module | if type == "array" then length else 1 end)"' "$SHIPPED") - if [ "$got" = "1,2" ]; then - echo "PASS: shipped ledger holds ONE invalid_actions_lock ack naming TWO modules" + got=$(jq -r '[.[] | select(.type == "invalid_actions_lock")] | length' "$SHIPPED") + if [ "$got" = "0" ]; then + echo "PASS: shipped ledger holds NO invalid_actions_lock ack" pass=$((pass + 1)) else - echo "FAIL: shipped invalid_actions_lock acks: expected 1 entry / 2 modules, got $got" + echo "FAIL: shipped invalid_actions_lock acks: expected 0, got $got" fail=$((fail + 1)) fi - # ⚠ The two emissions carry DIFFERENT file values — `actions.lock` from - # workflow_audit and the full path from WH004 — so the surviving entry must - # match by file_pattern. An exact `file` key would suppress only one of - # them and the other would red main. Both, or the collapse is unsound. + # Both emission paths, with their DIFFERENT file values — `actions.lock` + # from workflow_audit and the full path from WH004 — must reach the gate. cat > "$WORK/findings-shipped-pair.json" <<'EOF' [{"severity":"high","rule_module":"workflow_audit","type":"invalid_actions_lock","file":"actions.lock"}, {"severity":"high","rule_module":"workflow_hardening","type":"invalid_actions_lock","file":".github/workflows/actions.lock"}] EOF - assert_status "shipped ledger suppresses BOTH emission paths" \ - "$WORK/findings-shipped-pair.json" "$SHIPPED" "2,0" + assert_status "shipped ledger KEEPS both emission paths" \ + "$WORK/findings-shipped-pair.json" "$SHIPPED" "0,2" - # Over-match control: the collapse must not have turned the ack into a - # blanket amnesty for anything hypatia says about actions.lock. + # Nothing else hypatia says about actions.lock is muted either. cat > "$WORK/findings-shipped-other.json" <<'EOF' [{"severity":"high","rule_module":"workflow_audit","type":"shell_download","file":"actions.lock"}, {"severity":"high","rule_module":"workflow_lint","type":"invalid_actions_lock","file":"actions.lock"}] EOF - got=$(bash "$APPLY" "$WORK/findings-shipped-other.json" "$SHIPPED" advisory \ - | jq -r '"\(.findings_suppressed | length),\(.findings_kept | length)"') - if [ "$got" = "0,2" ]; then - echo "PASS: shipped ledger does NOT suppress other types or modules" - pass=$((pass + 1)) - else - echo "FAIL: shipped ledger over-matches: expected 0,2 got $got" - fail=$((fail + 1)) - fi + assert_status "shipped ledger does NOT suppress other types or modules" \ + "$WORK/findings-shipped-other.json" "$SHIPPED" "0,2" fi assert_invalid_option "invalid mode" bypass high