Skip to content

feat(cicd_rules): scorecard_wrapper_missing_job_permissions (#390)#404

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/gracious-mendel-WIXFG
May 30, 2026
Merged

feat(cicd_rules): scorecard_wrapper_missing_job_permissions (#390)#404
hyperpolymath merged 1 commit into
mainfrom
claude/gracious-mendel-WIXFG

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

What

Implements #390 — a new Hypatia.Rules.CicdRules detector, scorecard_wrapper_missing_job_permissions, for a silent-CI-failure class across the estate.

A .github/workflows/scorecard.yml that calls the standards scorecard-reusable.yml must grant security-events: write (and id-token: write) on the calling job. Called-workflow permissions are capped by the caller, so a wrapper that omits the grant leaves ossf/scorecard-action unable to upload its SARIF — every scheduled Scorecard run then fails with startup_failure and no logs. Estate baseline 2026-05-30: 37 affected wrappers (35 unique + 2 inert nested-monorepo copies). Prior art: julia-professional-registry#19, absolute-zero#68.

How

  • CicdRules.scan_scorecard_wrapper_permissions/2 — walks repo_path for every .github/workflows/scorecard.yml (root and nested monorepo copies) and emits a finding when the file references scorecard-reusable.yml and does not match ~r/security-events:\s*write/.
  • CicdRules.check_scorecard_wrapper_permissions/2 — pure (path, content) -> {:fail, finding} | :ok predicate behind the scan.
  • opts[:path_allow_prefixes] — substring carve-out for bespoke inline scorecard workflows that manage their own permissions shape. (Inline scorecard.yml that doesn't call the reusable is already ignored by construction.)
  • Finding shape %{rule:, severity: :high, file:, reason:, fix:} — the fix is a ready-to-paste permissions: block.
  • Surfaced through the Hypatia.Rules facade via defdelegate.
  • CHANGELOG.md + CHANGELOG.adoc entries.

Acceptance criteria (#390)

  • Rule emits a finding for each scorecard.yml satisfying the criterion
  • Recommended-fix snippet included in finding output (fix:)
  • path_allow_prefixes carve-out for inline (non-reusable) scorecard.yml

Tests

test/rules/cicd_rules_scorecard_wrapper_test.exs — sensitivity (positive + nested copy) and specificity (perm present, no-reusable, carve-out, irregular spacing), plus pure-predicate unit tests.

Honesty / CI note

  • Elixir/mix is not installed in this remote session (no deps, no _build), so I could not run mix test / mix format --check-formatted locally. The code follows the module's established conventions (single-line attribute strings; pipe-chain + nested-case mirroring the existing scan_content_patterns engine; ≤98-col lines). Please let CI run the suite — I'm flagging this rather than claiming green.
  • The rule is not auto-wired into the self-scan/dogfood loop, so it changes no existing scan behaviour; hypatia's own scorecard.yml already grants the perm, so it would be silent on this repo regardless.

Closes #390


Generated by Claude Code

Detect `.github/workflows/scorecard.yml` wrappers that call the standards
scorecard-reusable.yml but omit `security-events: write` on the calling
job. Called-workflow permissions are capped by the caller, so
ossf/scorecard-action cannot upload its SARIF and the scheduled Scorecard
run fails with `startup_failure` (silent CI failure, no logs). Estate
baseline 2026-05-30: 37 affected wrappers (35 unique + 2 nested copies).

- CicdRules.scan_scorecard_wrapper_permissions/2 walks the repo (root +
  nested monorepo copies); pure CicdRules.check_scorecard_wrapper_permissions/2
- opts[:path_allow_prefixes] carve-out for bespoke inline scorecard.yml
- finding carries severity/file/reason + a recommended fix snippet
- surfaced through the Hypatia.Rules facade via defdelegate
- test/rules/cicd_rules_scorecard_wrapper_test.exs: sensitivity (positive +
  nested) and specificity (perm present, no-reusable, carve-out, spacing)
- CHANGELOG.md + CHANGELOG.adoc entries

https://claude.ai/code/session_01J8oLNn6MjKDRRUF65e2jLf
@hyperpolymath hyperpolymath marked this pull request as ready for review May 30, 2026 22:48
@hyperpolymath hyperpolymath merged commit af8a772 into main May 30, 2026
1 of 31 checks passed
@hyperpolymath hyperpolymath deleted the claude/gracious-mendel-WIXFG branch May 30, 2026 22:49
hyperpolymath pushed a commit that referenced this pull request May 30, 2026
#403 WF018)

PR #404 added scorecard_wrapper_missing_job_permissions to cicd_rules.ex,
but PR #403 had concurrently implemented the same #390 detection as WF018
(check_scorecard_wrapper_missing_job_permissions) in workflow_audit.ex — its
canonical home alongside WF019/WF020. This removes the redundant cicd_rules
copy (rule, facade delegate, test, changelog entries); WF018 stays as the
single implementation.

Verified locally (Elixir 1.14): cicd_rules.ex compiles with zero warnings;
format-isolation confirms a pure deletion with no pre-existing reformat.

https://claude.ai/code/session_01J8oLNn6MjKDRRUF65e2jLf
hyperpolymath added a commit that referenced this pull request May 30, 2026
…F018) (#407)

PR #404 added scorecard_wrapper_missing_job_permissions to cicd_rules.ex, but #403 had concurrently implemented the same #390 detection as WF018 in workflow_audit.ex. Removes the redundant cicd_rules copy (rule, facade delegate, test, changelog); WF018 remains the single implementation. The #362 cron rule and #405 nodejs carve-outs are untouched.

Verified locally (Elixir 1.14): zero-warning compile; format-isolation shows a pure deletion.

https://claude.ai/code/session_01J8oLNn6MjKDRRUF65e2jLf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add cicd rule: scorecard_wrapper_missing_job_permissions

2 participants