Skip to content

[CJS-13028] Migrate Node 12 → 22.23.4 + runtime bump (CVE-2026-111497) - #3

Closed
Grant Matthews (grantmatthews18) wants to merge 1 commit into
mainfrom
grant/cjs-13028
Closed

Grant Matthews (grantmatthews18) wants to merge 1 commit into
mainfrom
grant/cjs-13028

Conversation

@grantmatthews18

Copy link
Copy Markdown

Summary

Patches CVE-2026-111497 and simultaneously fixes the fact that this action was pinned to Node 12, which GitHub Actions no longer supports as a runtime (likely already broken in CI anywhere it's used).

Changes

File Change
.nvmrc 12 → 22.23.4
action.yml using: 'node12' → using: 'node20'
.github/workflows/run_tests.yml Modernized to actions/checkout@v4, actions/setup-node@v4, node-version-file: '.nvmrc'; removes deprecated ::set-output and actions/setup-node@v1
@vercel/ncc 0.25.1 → 0.45.0 (0.25.1 fails on Node 17+ with ERR_OSSL_EVP_UNSUPPORTED)
dist/index.js Regenerated with new ncc so the bundle actually runs on modern Node

CVE reasoning

The reachable brotli decoder path (isomorphic-fetch → node-fetch@2 → zlib.createBrotliDecompress) is still bundled in dist/index.js, but it now runs on Node 20+ in GitHub Actions runners, which receive patched Node point releases. The dev-side .nvmrc is pinned to 22.23.4 explicitly.

A follow-up to migrate isomorphic-fetch → native fetch() (available on Node 18+) and bump using: to node24 would further harden this, but is out of scope for the CVE patch.

Test plan

  • npm test on Node 22.23.4: 47/47 passing
  • npm run build produces a working dist/index.js (71kB)

🤖 Generated with Claude Code

This action was pinned to Node 12, which is both long EOL and no longer
supported as a GitHub Actions runtime. Alongside the CVE patch:

- .nvmrc: 12 → 22.23.4
- action.yml: using: 'node12' → using: 'node20' (modern GH runtime)
- @vercel/ncc: 0.25.1 → 0.45.0 (older ncc broke on Node 17+ OpenSSL;
  needed for the dist/ rebuild)
- dist/index.js: regenerated with the new ncc so the bundle actually
  runs on current Node
- .github/workflows/run_tests.yml: modernized (actions/checkout@v4,
  actions/setup-node@v4, node-version-file: '.nvmrc'; removes the
  deprecated ::set-output and actions/setup-node@v1)

The reachable CVE path (isomorphic-fetch → node-fetch v2 → zlib.createBrotliDecompress)
is still present in dist/index.js by nature of the dep, but the host Node
runtime bumping to 20+ moves it off the un-patchable Node 12.

Advisory: https://vercel.com/kb/bulletin/node-js-security-advisory

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

- run: npm ci
- run: npm test
- uses: actions/checkout@v4

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static Code Analysis Risk: Software and Data Integrity Failures - GitHub actions artipacked vulnerability

By default, actions/checkout persists a GitHub token in the checked-out repository's .git/config file so subsequent git operations can authenticate. This token typically has write access to repository contents. The credential remains on the runner filesystem for all subsequent steps, meaning a compromised or malicious step could exfiltrate it. Additionally, if an actions/upload-artifact step packages the workspace -- including the .git directory -- into an artifact, the credential becomes downloadable by anyone with access. While the default GITHUB_TOKEN expires after the workflow run completes, this pattern is especially dangerous when a repository configures long-lived credentials such as personal access tokens (PATs) or deploy keys, which would remain valid well beyond the run.

Recommendation: Add persist-credentials: false in a with block directly under the actions/checkout uses line to prevent the token from being written to .git/config. If later steps need authenticated git operations, pass the token as a step-level environment variable (e.g., env: with GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}) rather than persisting it in the repository config where every subsequent step can access it.

Severity: Medium ⚠️
Status: Open 🔴

References:

  1. https://unit42.paloaltonetworks.com/github-repo-artifacts-leak-tokens/

More details:

🌻 View in Arnica


Take action by replying with an [arnica] command 💬

Actions

Use [arnica] or [a] to interact with the Arnica bot to acknowledge or dismiss code risks.

To acknowledge the finding as a valid code risk: [arnica] ack <acknowledge additional details>

To dismiss the risk with a reason: [arnica] dismiss <fp|accept|capacity> <dismissal reason>

Examples

  • [arnica] ack This is a valid code risk and I'm looking into it

  • [arnica] dismiss fp Dismissed - Risk Not Accurate: (i.e. False Positive)

  • [arnica] dismiss accept Dismiss - Risk Accepted: Allow the risk to exist in the system

  • [arnica] dismiss capacity Dismiss - No Capacity: This will need to wait for a future sprint

@grantmatthews18

Copy link
Copy Markdown
Author

Closing without merging — deferring on CVE patching for this repo.

Context

The action has been pinned to using: 'node12' since the initial release in Jan 2021. GitHub removed node12 as a supported runtime years ago, so any workflow invoking this action has been failing to execute on current runners since then.

Usage signals (public GitHub surface)

  • 0 issues ever opened — no bug reports, no feature requests
  • 0 external PRs — only Optimizely-internal commits
  • 0 matches for uses: optimizely/upload-custom-code-action in public code search
  • Only 2 entries in the GitHub Dependents graph, both personal test repos of Optimizely employees
  • No one has reported the action being broken despite it being broken for years

Reasoning for deferral

If real customers depended on this, we'd expect at least one bug report about node12 runtime errors. The silence over 2+ years of broken runtime is itself the signal: there is no production use.

Fixing the Node version wouldn't make anyone's workflow start working — nobody is invoking the action. The right next step is likely to archive the repository rather than carry CVE-patch overhead for a Marketplace listing with no users.

cc Micah Heineck (@micahheineckoptimizely) Istiak Bin Mahmod (@istiakbinmahmod) (recent committers) — flagging in case you have context I'm missing. Happy to reopen if there's actual production use I'm not seeing.

🤖 Posted via Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant