Skip to content

27 Scorecard callers omit actions:read and will startup_failure on their next standards pin bump #1035

Description

@hyperpolymath

Summary

27 Scorecard callers across the estate omit actions: read from their job-level
permissions: block. They are green only because their standards pin predates
2026-09-15. Each becomes startup_failure — silently, with no check run at all —
on its next pin bump.

metadatastician/burble is the index case: it bumped past the line in #230 and its
OSSF Scorecard is now startup_failure on main. Cure in
metadatastician/burble#231.

Mechanism

Two GitHub rules combine:

  1. A job-level permissions: block replaces the workflow-level map rather than
    merging with it.
  2. A called reusable workflow may not request more permission than its calling job
    holds.

So a caller that grants actions: read at workflow level and then declares a job
block without it passes actions: none to the callee. If the callee's own job
declares actions: read, that is an escalation and GitHub rejects the run at
startup
: zero jobs, no logs, no annotations, and no check run is created. The
workflow reads as absent from the checks list, not as red — which is why this has
gone unnoticed.

.github/workflows/scorecard-reusable.yml gained job-level actions: read at
a423e48a, 2026-09-15, "fix(ci): grant actions: read in the Scorecard
reusable"
— Scorecard's Packaging check calls Actions.ListWorkflowRunsByFileName.
That commit is the tripwire.

The predictor is a conjunction, not the omission alone

The caller omits actions: read AND the pinned callee declares it. Measured
controls:

repo caller pinned callee actions Scorecard
betlang has all four @bd0df9ea None success
laniakea omits actions @8f2ee508 None success
manifesto omits actions @8f2ee508 None success
burble (pre-fix) omits actions @0f2d9b54 read startup_failure

And for burble specifically, the callee declares it at both its old and new pin,
which is why the pin bump alone could not have cured it:

standards SHA job=scorecard actions
0f2d9b54 read
e977cc67 read
4d104d32 None

Honest counter-example

hyperpolymath/modshells is in the 27 and is currently startup_failure, but its
pinned callee (@81dbf2dd) does not declare actions, so this mechanism does not
explain it. It also has no actions.lock entry at all for scorecard.yml. Its
failure has a different, unidentified cause and needs its own diagnosis. Listed here
for completeness, not claimed as cured by this fix.

Population — 27 repos

Census over all 36 Scorecard callers in the estate clone set. Effective actions
scope resolved as job block if present, else workflow-level map.

repo job pinned standards source of perms
hyperpolymath/cloudflare-dns-terraform analysis 8f2ee508 job
hyperpolymath/ephapax scorecard 571cc734 job
hyperpolymath/feedback-o-tron scorecard 8f2ee508 job
hyperpolymath/julia-professional-registry scorecard 84355587 job
hyperpolymath/kitchenspeak analysis 571cc734 job
hyperpolymath/laniakea analysis 8f2ee508 job
hyperpolymath/lithoglyph scorecard 84355587 job
hyperpolymath/llm-grace analysis 8f2ee508 job
hyperpolymath/maa-framework scorecard 84355587 job
hyperpolymath/manifesto analysis 8f2ee508 job
hyperpolymath/methodologies scorecard 84355587 job
hyperpolymath/modshells analysis 81dbf2dd job
hyperpolymath/ochrance-framework scorecard 81dbf2dd job
hyperpolymath/phantom-metal-taste scorecard 81dbf2dd job
hyperpolymath/plasma-parser-writer scorecard d7c22711 job
hyperpolymath/rpa-elysium scorecard 84355587 job
hyperpolymath/safe-brute-force scorecard 81dbf2dd job
hyperpolymath/seamstress scorecard 84355587 job
hyperpolymath/session-sentinel analysis 8f2ee508 job
hyperpolymath/twingate-helm-deploy analysis 81dbf2dd job
hyperpolymath/vcl-ut scorecard 5a93d9d5 job
hyperpolymath/volumod scorecard 81dbf2dd job
hyperpolymath/wokelang scorecard 81dbf2dd job
metadatastician/chronicles-of-slavia scorecard fcb86691 job
metadatastician/first-post scorecard bd0df9ea job
metadatastician/harvard-dehallucinator scorecard bd0df9ea job
metadatastician/marid scorecard da2c748a job

Not affected — 9 repos: betlang, my-lang, scripts,
universal-chat-extractor (explicit actions: read in the job block);
hybrid-automation-router, pons-asinorum, proven-tests-and-benches,
metadatastician-governance (no job block — they inherit a workflow-level map that
already contains it, verified); burble (cured by #231).

What does not catch it

  • actionlint returns rc=0 on an affected file. It does not model
    reusable-workflow permission ceilings.
  • There is nothing to read after the fact. GET .../actions/runs/<id>/logs
    returns 404 on a startup_failure, /jobs returns 0, and there are no
    annotations.
  • A failing-checks list will not show it, because no check run is created.

Acceptance criteria

  • AC1 — All 27 repos have actions: read in the effective permission set for
    their Scorecard caller job.
  • AC2 — Re-running the census script yields 0 LATENT-MISSING.
  • AC3 — No repo's Scorecard regresses from success to any other state as a
    result of the change.
  • AC4 — A recurrence control exists: either the reusable documents its required
    caller scopes in-file, or a gate reports a caller whose effective permissions
    are a strict subset of the pinned callee's job-level declaration.
    (AC4 is the durable cure; AC1 alone is a one-time sweep that the next callee
    permission change will defeat.)
  • AC5 — modshells has a separate diagnosis recorded; it is not closed by
    AC1 evidence alone.

Note on scope

This is preventive, not a live outage: 26 of the 27 are green today. Filing under the
standing stopping rule — a new finding becomes an issue with acceptance criteria
rather than blocking anything in flight.

🤖 Generated with Claude Code

https://claude.ai/code/session_01X3hgXxWm6umMgZkjYyHnnm

Activity

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

    cicdCI/CD: workflows, actions, lockfiles, pins, runners, release gatesmeta:campaignCoordinated multi-repo push with a defined end state

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions