upvote
Public service announcement

You can pin actions versions to their hash. Some might say this is a best practice for now. It looks like this, where the comment says where the hash is supposed to point.

      Old -->   uses: actions/checkout@v4
      New -->   uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
There is a tool to sweep through your repo and automate this: https://github.com/mheap/pin-github-action
reply
The problem is actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 probably doesn’t do this same pinning, and the actions ecosystem is such an intertwined mess that any single compromised action can propagate to the rest
reply
Yes, true, but at least the fire won't spread through this one point. Hopefully all of your upstreams can be persuaded to pin also.
reply
Doesn't a single compromised action in the chain cause the whole to be fucked? Pinning the top level doesn't prevent any spread.
reply
Might want to vendor everything?
reply
Well, it is a git commit hash of the action repo that contains the transpiled/bundled javascript.

Like: https://github.com/actions/checkout/tree/11bd71901bbe5b1630c...

So I'm pretty sure that for the same commit hash, I'll be executing the same content.

reply
This is true specifically for actions/checkout, but composite actions can have other actions as dependencies, and unless the composite action pins the versions of its dependencies, it is vulnerable for this attack.

This article[0] gives a good overview of the challenges, and also has a link to a concrete attack where this was exploited.

[0]: https://nesbitt.io/2025/12/06/github-actions-package-manager...

reply
My preferred tool to solve these issues is called 'gitlab'
reply
Does it solve anything? I don't see this as a GitHub problem, it's a "we built a dependency management system with untrusted publishers" problem.

GitLab's `include` feature has the same concern. They do offer an integrity check, but it's not any more capable than hash pinning to a commit.

Fundamentally, if you offer a way to extend your product with externally-provided components, and you can't control the external publishers, then you've left the door open to 'these issues'.

reply
CircleCI

TravisCI

Jenkins

scripts dir

Etc

reply
yeah, github's business model is not really a git repository but a bunch of other (admittedly useful) stuff that traps people in their ecosystem.
reply
See also pinact[1], gha-update[2], and zizmor's unpinned-uses[3].

The main desiderata with these kinds of action pinning tools is that they (1) leave a tag comment, (2) leave that comment in a format that Dependabot and/or Renovate understands for bumping purposes, and (3) actually put the full tag in the comment, rather than the cutesy short tag that GitHub encourages people to make mutable (v4.x.y instead of v4).

[1]: https://github.com/suzuki-shunsuke/pinact

[2]: https://github.com/davidism/gha-update

[3]: https://docs.zizmor.sh/audits/#unpinned-uses

reply
I've always been worried about their backend changing and somehow named tags with a previous commit hash working for an attacker to give something you didn't expect for the commit hash.
reply
> There is a tool to sweep through your repo and automate this: [third-party]

Dependabot, too.

reply
This won't pin the action's dependencies, so it's a shallow approach only.
reply
Checkout v4 of course, released in August 2025, which already now pollutes my CI status with garbage warnings about some Node version being deprecated I could absolutely care less about. I swear half the problems of GitHub are because half that organization has some braindead obsession with upgrading everything everywhere all the time, delivering such great early slop experiments as "dependabot".
reply
I worry that CI just got overcomplicated by default when providers started rocking up with templated YAML and various abstractions over it to add dynamic behaviour, dependencies, and so on.

Perhaps mixing the CI with the CD made that worse because usually deployment and delivery has complexities of its own. Back in the day you'd probably use Jenkins for the delivery piece, and the E2E nightlies, and use something more lightweight for running your tests and linters.

For that part I feel like all you need, really, is to be able to run a suite of well structured shell scripts. Maybe if you're in git you follow its hooks convention to execute scripts in a directory named after the repo event or something. Forget about creating reusable 'actions' which depend on running untrusted code.

Provide some baked in utilities to help with reporting status, caching, saving junit files and what have you.

The only thing that remains is setting up a base image with all your tooling in it. Docker does that, and is probably the only bit where you'd have to accept relying on untrusted third parties, unless you can scan them and store your own cached version of it.

I make it sound simpler than it is but for some reason we accepted distributed YAML-based balls of mud for the system that is critical to deploying our code, that has unsupervised access to almost everything. And people are now hooking AI agents into it.

reply
You could use these shell script versions of pipelines in GHA though, right? There is nothing stopping you from triggering a bash script via a "run" step in YAML.

These reusable actions are nothing but a convenience feature. This discussion isn't much different than any other supply chain, dependency, or packaging system vulnerability such as NPM, etc.

One slight disclaimer here is the ability of someone to run their own updated copy of an action when making a PR. Which could be used to exfil secrets. This one is NOT related to being dependent on unverified actions though.

(re-reading this came across as more harsh than I intended.. my bad on that. But am I missing something or is this the same issue that every open-source user-submitted package repository runs in to?)

reply
I'm trying out SelfCI [1] for one of my projects and it's similar to what you were describing. My whole CI pipeline is just a shell script that runs the actual build and test commands, I can write a script in another language like python if I need more complexity and I can run it all locally at any time to debug.

[1] https://app.radicle.xyz/nodes/radicle.dpc.pw/rad%3Az2tDzYbAX...

reply
> GHA can’t even be called Swiss cheese anymore, it’s so much worse than that.

That's a high bar though. Few things are better than Swiss cheese.

reply
Salers (if you can find it)
reply
If you want more ammo for your ranting (no offense meant, I also rant): an issue as massive as https://github.com/orgs/community/discussions/142308 lingering for years should do the trick.
reply
It really feels like Firefox is not a supported browser on GitHub, I hit this and also find that much of the time the commit message is not correctly pulled from the PR description when that setting is enabled
reply
Meanwhile, bitbucket has never given us problems with several of our team using Firefox
reply
* no ipv6 support

* no ff merge support

* no sha2 commit hash support

reply
to be fair, git itself only supports sha256 (as opposed to all of sha2) and even then it's marked "THIS OPTION IS EXPERIMENTAL" so many are afraid to use it

ff merge support though....what a world that would be

reply
i had something similar with PRs last year. 2x PRs of mine disappeared for me. they were still counted in the total number of PRs and everyone else could see them.

0_o

reply