GitHub has set September 23, 2026 as the date when Node 20 will be removed from GitHub Actions runners. The deadline matters because JavaScript actions do not necessarily use the Node version your workflow installs for the application: they run on the runtime bundled with the runner, according to the runs.using field in the action metadata. Since June 16, 2026, Node 24 has already been the default for these actions; on September 23, Node 20 will no longer remain as a runner option.
In practice, the risk is not limited to workflows that explicitly mention “Node 20.” A YAML file may look current while still calling an old action whose action.yml declares node20. The purpose of the audit is therefore to locate action dependencies, test the complete set under Node 24, and fix incompatible runners before the cutoff.
What changes on September 23
GitHub's official timeline has been adjusted more than once. The August 25, 2026 editor's note moved the final removal date to September 23. Node 20 itself reached end of life in the Node.js project on April 30, 2026. GitHub began using Node 24 by default on June 16 and kept a temporary escape hatch for users that still needed Node 20.
- Until September 23: you can test ahead of time with FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true.
- Until September 23: the temporary opt-out ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true can still keep Node 20 in scenarios supported by the runner.
- After September 23: that opt-out stops working because Node 20 will be removed from the runner.
Primary source: GitHub Changelog — Deprecation of Node 20 on GitHub Actions runners. The Node.js release calendar confirms that the 20.x line reached end of life on April 30, 2026: Node.js Release schedule.
First: do not confuse the action runtime with your project's Node version
This is the most important distinction for avoiding a false sense of safety. JavaScript actions run on a copy of Node maintained inside the runner. The runner documentation describes executables in dedicated directories such as externals/node20 and externals/node24, and makes clear that this runtime is not the Node binary found on the PATH.
By contrast, actions/setup-node installs or selects the Node version used by your application commands, such as npm, pnpm, yarn, tests, and builds. A workflow can therefore install Node 22 or 24 for the project and, in the same job, execute an old action still packaged for Node 20. For the September 23 audit, the relevant version is the one declared by the JavaScript actions.
References: Actions runner Node.js Connection Check and actions/setup-node.
Workflow audit checklist
1. Inventory every action usage
Start with the files under .github/workflows and list every uses: occurrence. Include GitHub actions, third-party actions, reusable workflows, and local actions. In large repositories, searching YAML files for “uses:” is more reliable than reviewing each workflow visually.
Do not stop at the first level. A reusable workflow called from another repository may contain its own outdated actions. The same applies to a local composite action: it can chain other actions underneath.
2. Find which references still depend on node20
For every action in the inventory, open the exact version referenced by the workflow — tag, branch, or SHA — and inspect its action.yml or action.yaml. In a JavaScript action, look for runs.using. GitHub's metadata syntax currently accepts node20 and node24; the migration target is node24.
If the workflow is pinned to an old release, read the action's release notes. Important first-party actions have already moved: for example, actions/checkout documents Node 24 starting with the v5 line, and current actions/setup-node releases also use Node 24. Do not blindly jump to “the highest number”: major releases can include behavior changes that belong in your test plan.
References: Metadata syntax for GitHub Actions, actions/checkout, and actions/setup-node.
3. Force Node 24 on a test branch
Before changing every reference, run critical workflows with FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true set in the workflow or runner environment. GitHub provided this mechanism specifically to exercise the migration ahead of time. The goal is to cover builds, tests, artifact publishing, deployments, authentication, caches, and every step that relies on JavaScript actions.
The test should reproduce paths that normally appear only during releases or production. A workflow that passes on pull requests can still fail in a publishing job because that job calls different actions or targets different runners.
4. Audit self-hosted runners
The cutoff is also an infrastructure issue. GitHub states that Node 24 is incompatible with macOS 13.4 and earlier. In addition, Node 24 has no official ARM32 support, so ARM32 self-hosted runners will no longer be supported after Node 20 deprecation.
Update the runner software and inventory the operating system and architecture of each pool. This matters especially for organizations that keep frozen legacy images or build ephemeral runners from custom templates. September 2026 also has a second nearby deadline: on September 25, GitHub Enterprise Cloud starts full enforcement of a minimum self-hosted runner version. That is a separate timeline, but it can affect the same fleet.
References: Self-hosted runners reference and Minimum version enforcement timeline for self-hosted runners.
5. Treat your own actions as software that needs a release
If your organization maintains internal JavaScript actions, the fix does not end in the consumer YAML. The action must change its metadata to runs.using: node24, rebuild the distributed bundle when applicable, and pass integration tests. GitHub recommends automated testing and a clear release process for JavaScript actions, in part because dependencies are commonly distributed together with the compiled code.
After publishing a compatible version, update consumers in a controlled way. For third-party actions, GitHub recommends pinning to a full commit SHA when immutability is the priority; tags are more convenient but can move. A sound workflow for this migration is to validate the compatible release first and then pin the reference that actually passed your tests.
References: Releasing and maintaining actions and Secure use reference.
How to prioritize fixes
| Situation | Risk before Sept. 23 | Recommended action |
|---|---|---|
| Old external action with runs.using node20 | High | Upgrade to a Node 24-compatible release and test it |
| Internal JavaScript action on node20 | High | Migrate metadata, rebuild the bundle, and publish a new release |
| Self-hosted runner on macOS 13.4 or earlier | High | Upgrade the OS or move the job to another runner |
| ARM32 self-hosted runner | High | Plan an architecture migration; Node 24 has no official support |
| Workflow already passes with FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 | Lower | Remove outdated dependencies, consolidate refs, and repeat critical tests |
| Project uses Node 20 through setup-node but actions use Node 24 | Separate issue | Handle the application runtime migration separately; Node 20 is already EOL |
Plan rollback without relying on Node 20
Until September 23, ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true can serve as temporary containment. It is not a rollback plan for after the cutoff. Once the runtime is removed from the runner, no environment variable can restore it.
The useful rollback is different: keep the previous workflow commit, record the SHAs of tested versions, make the change through a pull request, and have a known Node 24-compatible reference for every critical action. If a major upgrade breaks behavior, you need to return to an earlier ref that is also Node 24 compatible — not to a version that depends on Node 20.
A practical sequence to finish before September 23
- Inventory every uses: occurrence across workflows, reusable workflows, and local actions.
- Classify which refs are JavaScript actions and inspect runs.using in the version actually consumed.
- Upgrade actions still tied to Node 20, reading the breaking changes for each major release.
- Run critical paths with FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true.
- Validate releases, deployments, artifacts, authentication, caches, and infrequent jobs.
- Update self-hosted runners, removing old macOS and ARM32 from the critical path.
- Pin tested refs and document a rollback that stays on Node 24.
- Remove temporary flags once the migration is stable.
The September 23 cutoff does not require a wholesale rewrite of CI, but it does require knowing exactly which actions your workflow executes and which runtime they were published for. Auditing now turns a platform change into a controlled dependency update; waiting until the removal date turns invisible dependencies into pipeline failures.





