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