Skip to content

feat(rules): WF017 — detect secret-consuming action without presence gate#396

Merged
hyperpolymath merged 1 commit into
mainfrom
rules-wf017-ungated-secret-action
May 30, 2026
Merged

feat(rules): WF017 — detect secret-consuming action without presence gate#396
hyperpolymath merged 1 commit into
mainfrom
rules-wf017-ungated-secret-action

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

Forward-detection rule for the pattern just root-fixed in hyperpolymath/standards#305 (Mirror radicle + Instant Sync secret-presence gates, 65 estate repos auto-fixed).

What WF017 detects

A workflow step that:

  • uses: one of @secret_consuming_actions (curated, data-driven)
  • reads \${{ secrets.X }} as its primary input
  • lacks an if: secrets.X != '' gate (on the step or as an enclosing wrapper)

Curated action list (initial)

Action Primary secret param
webfactory/ssh-agent ssh-private-key
peter-evans/repository-dispatch token
peter-evans/create-pull-request token
actions-ecosystem/action-create-comment github_token

Add new entries to @secret_consuming_actions (no code change).

Sensitivity / specificity smoke tests

Case Expected Result
Ungated webfactory/ssh-agent fires
Gated webfactory/ssh-agent (- if: secrets.X != '') silent
Ungated peter-evans/repository-dispatch fires
Gated peter-evans/repository-dispatch silent
Generic actions/checkout (not in list) silent

The gate regex handles both step-leading - if: and interior if:, both quote styles, and inline-\${{ … }} expressions.

🤖 Generated with Claude Code

…gate

Forward-detection rule for the pattern just root-fixed in
hyperpolymath/standards#305 (Mirror radicle / Instant Sync). Data-driven
list of known secret-consuming actions; new entries don't require code
changes.

## Detection

Fires when a workflow step:
  - uses one of the curated `@secret_consuming_actions`
    (webfactory/ssh-agent, peter-evans/repository-dispatch,
    peter-evans/create-pull-request, actions-ecosystem/action-create-comment)
  - reads `${{ secrets.X }}` as its primary input
  - lacks an `if: secrets.X != ''` (or env-equivalent) gate

## Why

Mirror radicle (26 repos) + Instant Sync (39 repos) caught on the
2026-05-30 estate audit. Both failed on every push on repos where the
required secret hadn't been propagated. Source fix in standards#305
makes the no-secret path a clean `::notice` skip; this rule prevents
the pattern from re-appearing in new workflows.

## Sensitivity / specificity

5/5 smoke tests pass:
  - ungated ssh-agent → fires
  - gated ssh-agent (`- if: secrets.X != ''` on the step) → silent
  - ungated repository-dispatch → fires
  - gated repository-dispatch → silent
  - generic actions/checkout (not in list, has token but uses GH_TOKEN) → silent

The gate regex matches both `- if: …` (step-leading) and `    if: …`
(interior key after a `- uses:` head), and both single- and
double-quote styles + inline-`${{ … }}` and bare expression forms.

Companion to PR #393 (WF014/WF015/WF016).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hyperpolymath hyperpolymath merged commit 386828d into main May 30, 2026
23 of 31 checks passed
@hyperpolymath hyperpolymath deleted the rules-wf017-ungated-secret-action branch May 30, 2026 16:53
hyperpolymath added a commit that referenced this pull request May 30, 2026
## Summary

Adds `[Unreleased] / Added` section to `CHANGELOG.adoc` enumerating the
four `workflow_audit` rules added in PRs #393 + #396 during the
2026-05-30 estate CI/CD audit.

## Why

Closing the documentation loop: the rules were merged with full `@doc`
blocks in code, but the CHANGELOG had no corresponding entry. Future
releases now have the right narrative.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 103 issues detected

Severity Count
🔴 Critical 0
🟠 High 0
🟡 Medium 103
View findings
[
  {
    "reason": "Action urin 21 JRE\n        uses: actions/setup-java@be666c2fcd27 needs attention",
    "type": "unpinned_action",
    "file": "verify-proofs.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in clusterfuzzlite.yml",
    "type": "missing_timeout_minutes",
    "file": "clusterfuzzlite.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

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.

1 participant