GitHub Actions Are a Security Nightmare

daddevmusings1 pts0 comments

Github Actions are a Security Nightmare

Cult’s Substack

SubscribeSign in

Github Actions are a Security Nightmare<br>How can we make supply chain attacks even worse?

Cult of Software Engineering<br>Aug 23, 2026

Share

A few weeks ago I read Efron Licht’s fantastic Github and the Crime against Software and had to shake my head at the inexorable entropic collapse of modern software engineering. Then, having learned nothing, I turned around and published the TTRPG app I built to learn Rust on Github. My users are not that technical, so the repository needs Github Releases with binaries to download. To convince my users that the binaries aren’t just totally_not_virus.exe, I decided to build the binaries with Github Actions.<br>If I don’t add this button, they make my article work in the acid mines. Subscribe if you want

Subscribe

Things immediately get sloppy

Learning yet another CI provider’s syntax is a pain, but Github helpfully provides a starter:

Which generates the following YAML:

Running this build resulted in an interesting warning:<br>Node.js 20 is deprecated. The following actions target Node.js 20 but are being forced to run on Node.js 24: actions/checkout@v4. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/

Huh? How does the official starter end up generating something deprecated? On a hunch, I asked ChatGPT to generate me a basic Github Actions CI Yaml for Rust. Sure enough, there was the outdated actions/checkout@v4.<br>Wait a damn minute, how the hell can checking out the repository - checking it out from Github using Github Actions - a CI that already has to look into the repo to see the Yaml file it’s executing! - how can the act of checking out that repository be deprecated?<br>Wait, why do I need to depend on an external Github Action to checkout the repository?<br>Wait, why does checkout have versions?<br>Wait, why is checking out the repository pulling in a node runtime???<br>Why checking out the repository is pulling in a node runtime

If you were naive like me, you might expect Github Actions to be reusable snippets of YAML. Define your shell script once and let others reuse it elsewhere; Gitlab’s CI lets you do this. Actually even Github Actions lets you do this!<br>Unfortunately, Github Actions you can pull in as dependencies are not repurposed YAML templates. These are full programs, invariably existing to replace a 1-2 line snippet of shell code. Actions/checkout - the official way to checkout your repository for Github Actions - has seven thousand lines of typescript.<br>I needed to create Github Releases for my app. The solution I went with was to use the Github CLI -<br>run: |<br>gh release create "${{ github.ref_name }}" --generate-notes

Do not copy! This was only not vulnerable to script injection because the ref_name was a tag that only I could push. I’m not even writing about script injection because everything else seems so much worse.<br>But why use Github’s CLI when I can instead add a unvetted external dependency to a node.js app to do this for me? There’s no shortage of candidates - while the official create-release Action is no longer maintained, it helpfully links you to four other security liabilities.

This official Github Actions Readme is five years old. I’m sure the links here would never become malicious.<br>Interestingly, the size of actions/checkout is not that much of an outlier. Woodpecker CI’s plugin-git has 1624 lines of Go; the git-plugin for Jenkins has 52883 lines of Java! Gitlab CI’s git integration will probably also be large.<br>But Woodpecker and Gitlab-CI don’t end up failing on this front, because:<br>Why would you need an external action to checkout a repository?

Getting your code checked out just works with Gitlab-CI and Woodpecker. These competitors have unsurprisingly identified this as a requisite core feature for a CI platform. Users can configure the checkout strategy, but the code for checking out the repository is just part of the CI. It is not possible to pull in a deprecated version of Gitlab CI’s GIT_STRATEGY because why, why would you ever make that even an option are you crazy?<br>While you’re at it, why not make checking out your code also result in surprise side-effects that make your pipeline vulnerable? Wait, I was joking, please don’t actually<br>actions/checkout also adds git authentication to all git calls for the rest of the job

Git checkout should not have to mean “attackers get to use my credentials to control my build pipeline”, but here we are. To be fair, Github Actions can be configured in a way to lower the permissions of the leaked key. Unfortunately, Github Actions also have an option that allow attackers to use trusted PRs to execute arbitrary Actions on your repository with a pwn-request attack. In 2021, Github Security Labs four parter(!) on Github Actions security vulnerabilities discussed this vulnerability exclusively in part one. Clearly some security engineers were concerned!<br>This...

github actions checkout repository security node

Related Articles