Skip to content

Reusable workflows reference secrets without declaring them, so callers cannot forward least-privilege names (WH008 is unsatisfiable fleet-wide) #1141

Description

@hyperpolymath

The problem, stated from the caller side.

workflow_hardening/WH008 flags secrets: inherit at a caller, and the estate's answer in every caller is currently "acknowledge it". The reason is not caller laziness: the reusables read secrets without declaring them under on.workflow_call.secrets, and GitHub only permits referencing an undeclared secret when it was inherited. Named forwarding is documented as a three-stage flow — declare in the reusable, reference in the reusable, pass by name from the caller — so until stage 1 exists, a caller's only options are secrets: inherit or a broken call.

That makes one upstream change the discharge condition for a fleet of acknowledgements (four in proven-tests-and-benches alone; standards itself carries the same entries for secret-scanner.yml, mirror.yml, hypatia-scan.yml, governance.yml).

on:
  workflow_call:
    secrets:
      GITLAB_SSH_KEY:
        required: false

required: false keeps every existing caller working — an absent secret resolves to the empty string exactly as it does today under inherit — while making named forwarding legal.

What each reusable would need to declare, read from the pinned revisions

reusable secrets referenced in the body where
mirror-reusable.yml @ bd0df9ea GITLAB_SSH_KEY, BITBUCKET_SSH_KEY, CODEBERG_SSH_KEY, SOURCEHUT_SSH_KEY, DISROOT_SSH_KEY, GITEA_SSH_KEY, RADICLE_KEY its own header already lists all seven and states inherit is mandatory
hypatia-scan-reusable.yml @ 71bb615e GITHUB_TOKEN, HYPATIA_SCAN_PAT line 129
secret-scanner-reusable.yml @ 84355587 GITHUB_TOKEN line 33 (the gitleaks action's inner token)
scorecard-reusable.yml @ da2c748a none a caller in proven-tests-and-benches had its secrets: inherit deleted outright — a reusable that reads no secret cannot need the whole scope

Worked example from a caller: hyperpolymath/proven-tests-and-benches — for the scorecard caller the inherit line was provably dead weight and has been removed; the other three are acknowledged in .hypatia-baseline.json with the discharge condition pointing here.

Why it matters beyond tidiness: secrets: inherit hands a reusable every secret the caller can see, including ones it will never read. With a declaration in place, a caller can pass exactly what the reusable needs, and WH008 becomes satisfiable rather than acknowledgeable — which is the difference between a gate the fleet can obey and one it must keep excusing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions