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
Context: The Hypatia scan on this repo reports 141 findings (64 critical / 56 high / 21 medium), but after per-finding investigation the large majority are scanner-side false positives or already-honored documented exemptions, not real defects in standards. The genuinely actionable in-repo items (missing timeout-minutes, malformed workflows, mirror SSH presence-gate, an AGPL→MPL header) were fixed in #361/#362/#364/#367 and are on main (383 workflows parse, 0 jobs missing a timeout, registry in sync).
This issue is the hand-off spec for the remaining "foundational/upstream" fixes, which live in hyperpolymath/hypatia (the detector source), not here. Each item below has the file, the false-positive proof, and the exact change.
Symptom:reason: "Action for the check script)\n uses: actions/checkout@de0f needs attention" on governance-reusable.yml. The ref is truncated to @de0f, the text "needs attention" + the "…check script)" prefix shows the detector is grabbing a preceding comment line plus the next uses: line.
Proof it's a false positive: every uses: across all 383 workflow files is pinned to a full 40-hex SHA, e.g. actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2.
Root cause: the canonical detector WH004 in lib/rules/workflow_hardening.ex is correct — it early-returns on Regex.match?(~r/@[a-fA-F0-9]{40}\b/, slug) and its reason is "pins … to a tag/branch — mutable ref allows upstream takeover". The findings here have a different rule_module (workflow_audit) and a different reason format, so a second, legacy unpinned-action emitter exists that (a) doesn't recognize 40-hex SHA pins, (b) truncates the SHA to 4 chars, (c) uses a brittle regex that captures an adjacent comment line.
Fix: remove/disable the legacy workflow_audit unpinned-action emitter and route solely through WH004. If it must remain, port WH004's 40-hex skip-guard into it and fix slug extraction to stop at first whitespace (drop trailing # comment) without truncation.
Proof it's a false positive: that step is gated — instant-sync.yml line 27: if: ${{ secrets.FARM_DISPATCH_TOKEN != '' }}, with a companion "skip" notice step for the empty case.
Root cause: the detector flags any secret-consuming action without recognizing a step-level (or enclosing-job) if: that presence-tests the same secret (!= '').
3. scorecard_publish_with_run_step — not scoped to the publish job
Module/severity:workflow_audit, high.
Symptom: flags scorecard-enforcer.yml for "split_scorecard_publish_job".
Proof it's a false positive: the publish job (scorecard) is already uses-only; the threshold check is already split into a downstream check-score job (needs: scorecard). The file even documents this in a comment.
Root cause: the detector scans the whole file for run: steps co-occurring with publish_results: true, instead of scoping to the job that contains the publish step. The run: steps are in other jobs (check-score, check-critical).
Fix: only emit if the job that runs ossf/scorecard-action with publish_results: true itself contains a run: step.
the retained Deno archetype scripts/check-ts-allowlist.ts (regression-suite target; documented in docs/EXEMPTION-MECHANISMS.adoc)
Ground truth: only 5 banned-language files exist in the repo (1 Python already in .hypatia-baseline.json, 4 TypeScript — all the carve-outs above). The reported "64 critical" is inflated/multi-counted; there are zero genuine violations.
Fix: apply the documented TS/RS/npm/JS path_allow_prefixes from CLAUDE.md in the deployed cicd_rules banned-language detector (config has drifted from policy). Consider downgrading grandfathered/in-flight-migration files below critical.
4b. missing_timeout_minutes (medium) fires on reusable-workflow CALLER jobs — governance.yml, mirror.yml, scorecard.yml, secret-scanner.yml. Their jobs are uses: reusable-workflow calls, where timeout-minutes is invalid YAML and cannot be added; the timeout belongs in the reusable workflow (already present).
Fix: skip jobs with a job-level uses: (reusable-workflow calls) in the missing_timeout_minutes check.
General
The reason strings for several finding types are malformed ("Issue in X.yml", embedded raw YAML, truncated refs) — the reason-builder/templating needs hardening so findings are actionable.
Filed as a hand-off; the fixes themselves belong in hyperpolymath/hypatia (lib/rules/workflow_hardening.ex, the workflow_audit module, lib/rules/cicd_rules.ex). This repo's side is complete.
Context: The Hypatia scan on this repo reports 141 findings (64 critical / 56 high / 21 medium), but after per-finding investigation the large majority are scanner-side false positives or already-honored documented exemptions, not real defects in
standards. The genuinely actionable in-repo items (missingtimeout-minutes, malformed workflows, mirror SSH presence-gate, an AGPL→MPL header) were fixed in #361/#362/#364/#367 and are onmain(383 workflows parse, 0 jobs missing a timeout, registry in sync).This issue is the hand-off spec for the remaining "foundational/upstream" fixes, which live in
hyperpolymath/hypatia(the detector source), not here. Each item below has the file, the false-positive proof, and the exact change.1.
unpinned_action— legacy emitter flags correctly SHA-pinned actionsworkflow_audit, medium.reason: "Action for the check script)\n uses: actions/checkout@de0f needs attention"ongovernance-reusable.yml. The ref is truncated to@de0f, the text "needs attention" + the "…check script)" prefix shows the detector is grabbing a preceding comment line plus the nextuses:line.uses:across all 383 workflow files is pinned to a full 40-hex SHA, e.g.actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2.lib/rules/workflow_hardening.exis correct — it early-returns onRegex.match?(~r/@[a-fA-F0-9]{40}\b/, slug)and its reason is "pins…to a tag/branch — mutable ref allows upstream takeover". The findings here have a differentrule_module(workflow_audit) and a different reason format, so a second, legacy unpinned-action emitter exists that (a) doesn't recognize 40-hex SHA pins, (b) truncates the SHA to 4 chars, (c) uses a brittle regex that captures an adjacent comment line.workflow_auditunpinned-action emitter and route solely through WH004. If it must remain, port WH004's 40-hex skip-guard into it and fix slug extraction to stop at first whitespace (drop trailing# comment) without truncation.2.
secret_action_without_presence_gate— doesn't recognize theif: secrets.X != ''gateworkflow_audit, high.instant-sync.yml(peter-evans/repository-dispatch).instant-sync.ymlline 27:if: ${{ secrets.FARM_DISPATCH_TOKEN != '' }}, with a companion "skip" notice step for the empty case.if:that presence-tests the same secret (!= '').if:referencing the same secret with a!= ''presence test. (Same pattern now used inmirror-reusable.ymlafter ci(workflows): presence-gate mirror SSH steps + correct registry-verify licence #367 — it will otherwise keep being false-flagged.)3.
scorecard_publish_with_run_step— not scoped to the publish jobworkflow_audit, high.scorecard-enforcer.ymlfor "split_scorecard_publish_job".scorecard) is already uses-only; the threshold check is already split into a downstreamcheck-scorejob (needs: scorecard). The file even documents this in a comment.run:steps co-occurring withpublish_results: true, instead of scoping to the job that contains the publish step. Therun:steps are in other jobs (check-score,check-critical).ossf/scorecard-actionwithpublish_results: trueitself contains arun:step.4. Carve-out / semantics gaps (
cicd_rules+workflow_audit)banned_language_file(critical) ignores documentedpath_allow_prefixes. Flags files that CLAUDE.md explicitly exempts:**/bindings/deno/**(interop) →a2ml/bindings/deno/mod.ts,k9-svc/bindings/deno/mod.ts**/vitest.config.ts(tooling) →lol/test/vitest.config.tsscripts/check-ts-allowlist.ts(regression-suite target; documented indocs/EXEMPTION-MECHANISMS.adoc).hypatia-baseline.json, 4 TypeScript — all the carve-outs above). The reported "64 critical" is inflated/multi-counted; there are zero genuine violations.path_allow_prefixesfrom CLAUDE.md in the deployedcicd_rulesbanned-language detector (config has drifted from policy). Consider downgrading grandfathered/in-flight-migration files belowcritical.missing_timeout_minutes(medium) fires on reusable-workflow CALLER jobs —governance.yml,mirror.yml,scorecard.yml,secret-scanner.yml. Their jobs areuses:reusable-workflow calls, wheretimeout-minutesis invalid YAML and cannot be added; the timeout belongs in the reusable workflow (already present).uses:(reusable-workflow calls) in themissing_timeout_minutescheck.General
The
reasonstrings for several finding types are malformed ("Issue in X.yml", embedded raw YAML, truncated refs) — the reason-builder/templating needs hardening so findings are actionable.Filed as a hand-off; the fixes themselves belong in
hyperpolymath/hypatia(lib/rules/workflow_hardening.ex, theworkflow_auditmodule,lib/rules/cicd_rules.ex). This repo's side is complete.https://claude.ai/code/session_01AmPXB2dA2wCcabo8BXwS28