Skip to content

v0.1.6: job-level reusable-workflow uses: refs are invisible — missed desync, false stale, and fix mode prunes a correct entry #129

Description

@hyperpolymath

Summary

gh actions-lock v0.1.6 does not appear to consider job-level reusable-workflow uses:
refs (jobs.<id>.uses:) when reconciling workflows against actions.lock. GitHub's own
startup validation does enforce them, so the tool disagrees with the platform in both
directions:

  1. a missed desync that caused a real startup failure and was reported by nothing, and
  2. a false stale on a ref that is present in the workflow.

Consequently fix mode would prune a lockfile entry that is actually required, reintroducing
the startup failure.

Environment

  • gh actions-lock v0.1.6 (gh extension install github/gh-actions-lock --pin v0.1.6)
  • lockfile version: 'v0.0.2', 30–31 workflows
  • public repository, Linux runner and local Linux both reproduce

1. Missed desync (false negative) — caused a startup failure

A workflow whose only uses: is job-level:

# .github/workflows/mirror.yml
jobs:
  mirror:
    uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@4d104d325b96c348d685956c6678139640c15c4b

actions.lock recorded the previous commit under that path:

workflows:
    '.github/workflows/mirror.yml':
        - 'hyperpolymath/standards@d135b05b...'

Observed:

  • GitHub refused to start the run — zero jobs created, no log, only
    "This run likely failed because of a workflow file issue."
  • gh actions-lock --no-fix → not reported
  • gh actions-lock --verify-local → not reported; output was
    "All 30 workflows have complete lockfile coverage"
  • fix mode → did not repair the entry

So a desync that GitHub treats as fatal is invisible to all three modes.

2. False stale (false positive)

A different workflow with a job-level ref on line 144:

# .github/workflows/release.yml:144
    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a # v2.1.0

This ref was absent from the lock entirely and was not reported as missing. After adding
the required entry by hand, --verify-local reports:

{
  "workflow": ".github/workflows/release.yml",
  "category": "stale",
  "severity": "warning",
  "confidence": "high",
  "dependency": "slsa-framework/slsa-github-generator@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a",
  "detail": "lockfile pins slsa-framework/slsa-github-generator@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a but no uses: in this workflow references it",
  "remediation": "remove the entry or re-run `gh actions-lock`"
}

The claim "no uses: in this workflow references it" is false; the ref is on line 144.

Following the remediation — removing the entry — reintroduces the startup failure from §1.

Why the two cases differ

mirror.yml parses 0 step-level refs, so the stale check appears to be skipped for it.
release.yml parses 9 step-level refs, so the unmatched job-level entry looks orphaned. That
also means fix mode would prune the correct slsa entry as stale, which is the most
damaging consequence: running the tool on a correct lockfile makes it incorrect.

Suggested fix

Treat jobs.<id>.uses: as a dependency reference, normalising
owner/repo/.github/workflows/<file>@<ref> to owner/repo@<ref> the same way action subpaths
are normalised today, for coverage, staleness and fix mode alike.

Related

severity is warning for both stale and sha-as-ref, so downstream tooling cannot use
severity to distinguish an advisory finding from a blocking one. That may be worth separating.

Reported separately: the management banner is not idempotent and fix mode de-pins bare SHAs (#130).

🤖 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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions