↓ Skip to main content
  1. Tech Blog: AI, Security, Infrastructure & Open Source/

GitHub Actions Drops Node 20 — What You Need to Change

·912 words·5 mins
Osmond van Hemert
Author
Osmond van Hemert
Developer Tooling - This article is part of a series.
Part : This Article

GitHub Actions has stopped carrying Node 20 on its runners. In its September 23 final notice, GitHub says JavaScript actions now use Node 24 and the temporary ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION opt-out no longer works. This is a change to the runtime that executes JavaScript actions—not an order to make every application in CI run Node 24.

That distinction determines what you should change. Action authors own the action’s runtime and published code; workflow owners choose action versions; self-hosted runner operators must check the machine that hosts both. Treating all three as a single “bump Node” task risks changing your application’s test matrix while overlooking the action that actually needs attention.

What Changed on September 23
#

GitHub’s earlier deprecation schedule says runners began using Node 24 by default on June 16, 2026, while an environment-variable opt-out allowed a temporary return to Node 20. September 23 ended that transition: the final notice says Node 20 is no longer available on runners. This applies to github.com and GitHub with Data Residency; don’t assume the announcement also describes a separate GitHub Enterprise Server installation.

A JavaScript action declares its execution runtime in action.yml or action.yaml. GitHub’s action metadata reference shows the Node 24 declaration:

runs:
  using: node24
  main: dist/index.js

The runner uses that runtime for the action’s entrypoint and, where configured, its pre- and post-scripts. It is separate from the version of Node your repository installs for a shell command. GitHub’s own setup-node metadata declares using: 'node24', but its node-version input selects the version put on PATH for subsequent workflow commands. A workflow that uses a current setup-node release to test an application on Node 20 is therefore not, by that fact alone, requesting the retired action runtime.

If You Maintain a JavaScript Action
#

Start with the published action, not just its development branch. Change runs.using to node24, test the action’s main and any pre/post paths on supported runner operating systems, and release a version that workflow owners can actually reference. If your action checks in a compiled or bundled dist/ entrypoint, rebuild and publish that artifact too; changing metadata without shipping the JavaScript it points to is an incomplete release.

GitHub explicitly asks maintainers to update runs.using and publish a new release. A runner moving old JavaScript action code to a new runtime does not establish that your dependencies, native modules, or tests are compatible. Run your own action against a representative fixture rather than inferring success from the absence of a workflow warning.

If your repository only defines a composite action or a Docker container action, its top-level runs.using is composite or docker, not a Node runtime. Check any JavaScript actions it calls, but don’t mechanically change those declarations to node24. The metadata reference distinguishes these action types.

If You Use Actions in Workflows
#

Inventory third-party uses: steps and look up the action release each one references. GitHub says its newest first-party action versions have moved to Node 24; it asks workflow owners to upgrade to action versions that support Node 24. A version tag in your YAML does not tell you what runtime its author declared or whether its published bundle was tested on it. For an unfamiliar action, inspect the referenced release’s action.yml, release notes, and CI results before updating the workflow.

A quick local search helps you find your own legacy declarations and obsolete opt-outs:

rg -n 'node20|ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION' .github

It will not reveal what a remote action referenced by uses: owner/repo@version ships. Review those references separately and run the workflow on the runner platforms you actually support. Don’t confuse a node-version: 20 input to setup-node with runs.using: node20 in an action’s metadata: one controls the project’s shell-step Node version, the other describes the action runtime.

This is also a good moment to review which third-party actions you trust, not only which version they run. My earlier analysis of the tj-actions supply-chain compromise explains why an apparently small action update deserves the same scrutiny as other executable CI dependencies. That security decision is separate from the Node migration; don’t use an urgent runtime change as a reason to skip review.

Self-Hosted Runners Need an OS Check
#

GitHub’s final notice says Node 24 is incompatible with macOS 13.4 and earlier and does not officially support ARM32; self-hosted runners on those systems are no longer supported for this transition. If you operate a self-hosted fleet, inventory the hosts and validate a Node-24-based action on each supported OS and architecture before treating green checks on a GitHub-hosted Linux runner as proof your fleet is ready.

The larger lesson reaches beyond this upgrade. GitHub Actions made CI easy to adopt, but an action brings its own execution environment into every workflow that calls it. Keep an inventory of action versions and runner platforms alongside your application’s language-version matrix; they are different dependencies with different owners.

My Take
#

The dangerous response to this announcement is a bulk edit of every 20 in a workflow. That might change the software you test while doing nothing for a stale third-party action or an unsupported self-hosted runner. First identify which layer each version controls; then migrate and test the layer GitHub actually removed.

I’d treat September 23 as a release-management deadline, not merely a warning-cleanup exercise. Action maintainers need a tested Node 24 release, workflow owners need to select it deliberately, and runner operators need to verify their hosts. The next runtime cutoff will be much less disruptive for teams that already track those three inventories separately.

Developer Tooling - This article is part of a series.
Part : This Article

Related