deniz.in

Markets

Weather

Loading weather

· via dev.to (home feed)

pin-deep recursively checks whether pinned GitHub Actions pin their own dependencies

A new Python tool called pin-deep walks the dependency tree of SHA-pinned GitHub Actions and flags any nested uses: reference floating on a tag or short hash instead of a full commit SHA.

pin-deep recursively checks whether pinned GitHub Actions pin their own dependencies

A new open-source tool called pin-deep targets a gap in GitHub Actions supply-chain security that conventional pinning advice does not cover: the dependencies of the actions you pin. Announced in a dev.to post and published on PyPI, the Python package recursively audits a workflow file and reports every nested uses: reference that is not locked to a full commit SHA.

The standard guidance is to pin uses: lines to a commit SHA so a hijacked tag cannot silently rewrite your CI. The dev.to post argues this only secures the first hop, and cites the tj-actions compromise tracked as CVE-2025-30066 as the canonical case: according to the post, victims were reached through reviewdog, which referenced the compromised action. Pinning reviewdog itself did not help, because the weak link was inside a dependency of something those victims had already pinned.

How it works

pin-deep takes either a workflow file or a single pinned uses: value. It fetches the action.yml of every action pinned to a full commit SHA, reads the nested uses: entries declared there, and repeats the process down to a configurable depth, with cycle protection against circular references. Every nested reference that resolves to a tag, a branch, or a shortened hash is flagged together with the depth, the manifest it came from, and the full chain from your workflow down to the offending entry. The sample output in the post shows actions/cache@v3 caught at depth 2, reached through a pinned actions/setup-python SHA.

Design decisions

Several implementation choices shape what the tool actually guarantees. Recursion happens only through full SHAs: a floating tag has no fixed content, so auditing its children would inspect whatever the tag points at today rather than what you actually ship. Unpinned refs are flagged but never followed. Short hashes count as warnings rather than passes, since a seven-character prefix resolves but is weaker than a full 40- or 64-character SHA, and a --strict flag makes those findings fail the run as well.

The default depth is 3, which the post describes as deep enough to catch a hole like the reviewdog one while keeping the scan quick. The tool exits with status 1 when it finds anything, so it can gate CI directly. GITHUB_TOKEN serves as an API fallback, and the post says public repositories need no credentials at all. The package is also written against the Python standard library alone, with no runtime dependencies.

How it compares with existing linters

Static workflow linters such as zizmor examine the uses: lines in your own workflow files. According to the author, the distinguishing feature of pin-deep is the recursive step beyond that: checking what your pinned actions themselves depend on, transitively. The post claims no other tool performs this nested check, framing pinning depth as its own auditable dimension. That uniqueness claim comes from the project's own announcement, so it is best read as a design goal rather than a verified survey of the landscape.

Why it matters

The tj-actions incident showed that an Actions supply-chain attack does not need to compromise the action you named; one indirection is enough. If a pinned action references a floating tag, your effective security is only as strong as the weakest ref in that transitive chain, something first-hop pinning cannot express or even reveal. GitHub Actions offers no native mechanism for locking transitive references, so by default that entire layer goes uninspected.

That makes a cheap, exit-code-driven checker a sensible CI addition: it either passes or hands you the exact chain of actions behind a finding, and because it recurses only through full SHAs, every floating ref it encounters marks precisely where the audit stops. Independent evaluation of the tool is still thin given its fresh announcement, but the class of risk it surfaces is real, already demonstrated in the wild, and largely invisible to the linting most pipelines run today.

  • #github-actions
  • #supply-chain-security
  • #ci-cd
  • #python
  • #open-source

Related posts