Repository navigation
RFC: rebuild agent images for Node.js security releases (Node 22.23.4 / 24.22.1) #1567
Description
Summary
The Node.js security release of 2026-10-21 fixes CVE-2026-111497, a Brotli decoder out-of-bounds write that permits remote code execution, along with other issues. The fixed versions are 22.23.4 and 24.22.1. No released openab agent image includes these versions yet: stable-<agent> has Node 22.23.1, and beta-<agent> has 22.23.3. The stable-* images also missed the earlier security release (22.23.2, 2026-07-28).
The problem is in how images are published. The Node base image is a floating tag, but stable releases are re-tagged instead of rebuilt, and no workflow rebuilds release images when the base image changes.
This RFC proposes:
- Ship patched images now.
- Pin the Node version with a build ARG.
- Add a daily check that opens an issue when a newer Node security release exists.
- Add a release-note template for these releases.
The exposure in openab is unclear and possibly low (see Exposure). The fix costs only a rebuild.
Motivation
Users who pull the newest openab release or beta tag today get a Node.js runtime that has known High-severity CVEs, and nothing in the current release flow will change that until the next minor release. The sections below show the advisory, which images are affected, what is published, and why.
Advisory
From the Node.js October 2026 security releases, these High-severity issues affect 22.x and 24.x:
| CVE | Severity | Title |
|---|---|---|
| CVE-2026-111497 | High | Node.js Brotli decoder out-of-bounds write permits remote code execution |
| CVE-2026-106069 | High | TLS certificate hostname bypass when the host loosely resolves to an IP address |
| CVE-2026-105482 | High | dns.resolve truncates names containing NUL char |
Fixed versions: 22.23.4, 24.22.1, 26.12.1.
Which images contain Node
node:22-trixie-slim(base-node): claude, codex, copilot, gemini, mimocode, opencode, pinode:24-trixie-slim: kimi- No Node: kiro, cursor, grok, devin, antigravity, native, agentcore, gateway
What is published
Measured on 2026-10-22 by running node --version in each image (linux/amd64, fresh anonymous pull). The results match the NODE_VERSION value in each image config. All agents in a row show the same version.
Tag (ghcr.io/openabdev/openab) |
Source | Built | Node | Fixed |
|---|---|---|---|---|
stable-<agent>, 0.9-<agent>, 0.9.0-<agent> |
v0.9.0 (promoted from beta.12) | 2026-07-19 | 22.23.1 | no |
beta-<agent>, 0.10.0-beta.5-<agent> |
v0.10.0-beta.5 | 2026-09-26 | 22.23.3 | no |
pre-beta-<agent> |
main | 2026-10-03 | 22.23.3 | no |
nightly-<agent> |
main + vendor-latest CLIs | 2026-10-22 | 22.23.4 | yes |
beta-kimi, pre-beta-kimi (no stable-kimi) |
24.21.0 | no | ||
nightly-kimi |
2026-10-22 | 24.22.1 | yes |
The deprecated per-agent repositories (openab-claude, openab-codex, openab-gemini, openab-copilot, openab-opencode, openab-pi, openab-mimocode) were last built on 2026-06-21 on Debian bookworm with Node 22.23.0. No release workflow builds them anymore, and their stable and latest tags point at 0.8.5.
Why released images go stale
FROM node:22-trixie-slimfloats, so the Node version changes only on rebuild.promote-stableinbuild-operator.ymlre-tags the last beta and does not rebuild. This is by design ("what you tested is what you ship"). As a result,stable-<agent>keeps that beta's Node version until the next stable release.- No workflow rebuilds release images when the base image changes.
nightly-build.ymlrebuilds daily withno-cacheand picked up 22.23.4 within a day, but nightly is not a release channel. - There is no Dependabot or Renovate configuration.
Exposure
Unclear, and possibly low. This RFC does not demonstrate an exploit path.
-
No Node server on a network port by default. openab and the gateway are Rust. Neither the Dockerfiles nor the chart start a Node server on a network port, so the scenario "server accepts Brotli request bodies" does not apply to a default deployment. A user-configured MCP server that uses the HTTP transport could change this.
-
Node processes are mostly outbound clients. The npm metadata of the pinned versions shows which CLIs run on the image's Node:
Agent Runs on the image's Node claude claude-agent-acp(JS). Claude Code itself ships as a native binary.gemini, pi (+ pi-acp), kimiYes (JS bundles) codex, copilot, opencode, mimocode Only a JS launcher. The CLI is a per-platform native binary. MCP servers started with npxYes -
Possible client-side path (not verified). Node's
fetchdecompressesContent-Encoding: brresponses automatically. A JS agent that fetches an attacker-chosen URL may therefore decode attacker-controlled Brotli data. Whether CVE-2026-111497 is reachable this way has not been verified. -
TLS hostname bypass. CVE-2026-106069 affects outbound HTTPS from the same processes. An attacker needs a position on the network path to use it.
Proposal
1. Immediate: ship patched images
- Beta: Cut
0.10.0-beta.6from main through the normal Release PR flow. The floating base already resolves to 22.23.4 / 24.22.1. Verifynode --versiononbeta-<agent>. If the Actions cache returns old layers, re-run withgh workflow run build-operator.yml -f tag=v0.10.0-beta.6 -f no_cache=true. - Stable: Choose one option:
- (a)
0.9.1, with no code changes. Branch fromv0.9.0, bumpCargo.tomlandChart.yaml, then push the tagsv0.9.1-beta.1andv0.9.1by hand.release-pr.ymlandtag-on-merge.ymlsupport main only. - (b) Promote
0.10.0after beta.6 is tested. Users onstable-<agent>move to a new minor version.
- (a)
- Not rebuilt: 0.8.x, 0.9.0-beta.x, and the deprecated per-agent repositories. The release note tells users of those tags to migrate.
- Version tags stay immutable. Do not overwrite existing version tags such as
0.9.0-claude.
2. Pin the Node version with a build ARG
ARG NODE22_VERSION=22.23.4
ARG NODE24_VERSION=24.22.1
FROM node:${NODE22_VERSION}-trixie-slim AS base-node
FROM node:${NODE24_VERSION}-trixie-slim AS kimiApply this to Dockerfile.unified, Dockerfile.package, and the per-agent Dockerfiles. Extend the smoke tests to:
- assert that
node --versionmatches the ARG, the same way the tests already read the CLI version ARGs; - assert that the ARG has the same value in every file, the same way they already do for
KIRO_CLI_VERSION.
| Float (today) | Pin version tag (proposed) | Pin digest | |
|---|---|---|---|
| Node version visible in the repo | no | yes | yes |
| Debian fixes picked up on rebuild | yes | yes | no |
| Reproducible | no | Node only | yes |
| Upkeep | none | one-line PR per Node release | PR per upstream image rebuild |
The pin alone does not fix the stale-stable problem. It makes the Node version explicit and checkable, and the bump PR records the change.
3. Prevention: daily node-security-check.yml
A daily workflow (also runnable with workflow_dispatch), about 60 lines of bash and jq. It needs only GITHUB_TOKEN with issues: write.
- Read
NODE22_VERSIONandNODE24_VERSIONfromDockerfile.unified. - Fail if
https://nodejs.org/dist/index.jsonlists a newer release withsecurity: truein the same major version. - Read
NODE_VERSIONfrom the configs of the publishedstable-<agent>andbeta-<agent>images, using an anonymous registry request without pulling the images. Report every image that is behind. This catches the current case, where main is fixed but the released tags are not. - Open an issue, or update the existing one, with the advisory link and the list of stale tags.
Non-security Node patch releases do not trigger it.
Dependabot is not part of this proposal. It cannot parse an ARG-templated FROM line, and it does not cover the release step, which is where the gap is.
4. Runbook and release-note template
Add a "Base image security release" section to RELEASING.md. The steps are: the check opens an issue, a PR bumps the ARG, the next beta is cut, Node is verified in beta-<agent>, the stable path from step 1 is followed, and the note is posted. In the same PR, fix the outdated references in RELEASING.md: build.yml is now build-operator.yml, and the image list still names the per-agent repositories.
Release-note template:
### Security: Node.js base image update (<22.x.y> / <24.x.y>)
This release rebuilds the Node-based agent images to include the Node.js <Month YYYY> security release: <advisory URL>. <There are no openab code changes. | Other changes: ...>
**Rebuilt:** `openab:<version>-<agent>` for claude, codex, copilot, gemini, kimi, mimocode, opencode, pi. The kiro, cursor, grok, devin, antigravity, native, and agentcore images do not contain Node.
**Floating tags now point at the fixed build:** `stable-<agent>`, `<major.minor>-<agent>`, `beta-<agent>`.
**Not rebuilt (still vulnerable):** `openab:<previous versions>-<agent>` and every tag in the deprecated per-agent repositories (`openab-claude`, ...). To migrate, see docs/image-tags.md.
**Exposure in openab:** <one or two sentences; say what is verified and what is not>
**Verify:** `docker run --rm --entrypoint node ghcr.io/openabdev/openab:<tag> --version`Alternatives considered
- Rebuild and overwrite existing version tags. Rejected. It breaks pinned deployments and the rule "what you tested is what you ship".
- Point deprecated repository tags (
openab-claude:stable) at the new unified images. Rejected. Users would move from 0.8.5 to 0.9.x or 0.10 without notice. - Scheduled automatic rebuild and republish of stable. Rejected. It publishes untested builds under stable tags, and nightly already serves as the rebuild lane.
- Dependabot or Renovate. Not proposed now, for the reasons in Proposal §3. Renovate with a regex manager could be added later next to the check.
Rollout
Steps 1–3 do not depend on steps 4–6.
- Cut
0.10.0-beta.6and verify Node inbeta-<agent>. - Decide the stable path (option a or b) and ship it.
- Post the security note.
- Open a PR for the Node ARG pin and the smoke-test assertions.
- Open a PR for
node-security-check.yml. - Open a PR for the RELEASING.md runbook and the outdated-reference fixes. If maintainers want an ADR in
docs/adr/, a draft is ready.
Open questions
- Support policy. There is no SECURITY.md and no list of supported lines. Is 0.9 still supported now that 0.10 has been in beta since July? The answer decides between option (a) and option (b).
- Patch releases outside main. Is it acceptable to push tags by hand from a
v0.9.0branch? The OCI chart is published bybuild-operator.yml, but the GitHub Pages index (release.yml) is updated only on pushes to main. - beta.6 contents. beta.6 includes everything merged since beta.5, including the breaking cron change (fix(cron)!: treat blank thread_id/id as unset; document thread_id/id behavior #1564). Is that acceptable for a security-motivated release?
- Deprecated repositories. Add a deprecation notice, or remove them?
- Nightly. Should nightly follow the pinned Node version or keep floating?
- Reachability. Can someone confirm or rule out the
fetchBrotli path for the JS agents?
摘要(繁體中文)
Node.js 在 2026-10-21 發布 security release,修補了 Brotli decoder 的 RCE 漏洞(CVE-2026-111497)等問題,修正版本是 22.23.4 和 24.22.1。
實測結果:stable-*(Node 22.23.1)和 beta-*(22.23.3)都還沒修補,只有 nightly-* 已經更新。原因是 stable 只重新貼 tag、不會 rebuild,而且 Node base image 有新版時沒有任何機制觸發重建。舊的 openab-claude 等 per-agent repo 已經淘汰,之後也不會再更新。
影響評估:預設部署沒有 Node server 開放對外 port,實際風險不明,可能偏低。
提案:
- 立即發布 0.10.0-beta.6;stable 走 0.9.1 或 0.10.0。
- 用 build ARG 釘住 Node 版本。
- 每天檢查 Node security release,版本落後時自動開 issue。
- 提供 release note 範本。
歡迎討論。
Activity
chaodu-obk commentedon Oct 22, 2026
Thanks for the thorough RFC. The measurements and root-cause analysis are clear. Maintainer decisions below (confirmed by @pahud):
Decisions
0.10.0-beta.6, verifynode --versiononbeta-<agent>(22.23.4 / kimi 24.22.1), then promote to0.10.0. Target: promote within about one week after beta.6 is verified, sostable-*does not sit on 22.23.1 longer than necessary.v0.9.xbranch.cronjob.tomlfor usercron ids that are equal after trimming and make them unique before upgrading. Stable users jump from 0.9 to 0.10 in one step, so this needs to be prominent.openab-claude:stableetc. will hitImagePullBackOffon the next pull. Deletion is done by an org admin.node --version== ARG" must be skipped or warn-only on nightly builds.Left to PR review (no decision needed)
node-security-check.yml: we suggest opening/updating a single labeled issue rather than failing the workflow daily (a red check every day gets ignored). Cover both the 22 and 24 (kimi) lines.fetchBrotli reachability): would be good to confirm, but it does not block the release.Next steps
0.10.0-beta.6and verify Node inbeta-<agent>.0.10.0; post the security + breaking-change release note (include the per-agent repo deprecation notice and deletion date).node-security-check.yml, RELEASING.md runbook + SECURITY.md + outdated-reference fixes.@antigenius0910 the PRs for step 3 are yours if you'd like to take them. Thanks!
chaodu-obk commentedon Oct 23, 2026
Status update and dates (confirmed by @pahud):
Step 1 —
0.10.0-beta.6: released via #1568 (tagv0.10.0-beta.6). Image builds are in progress. Node versions inbeta-<agent>(22.23.4, kimi 24.22.1) will be verified from the published image configs once the build completes, and reported here.Step 2 — dates:
0.10.0(stable) from beta.6, if no blocker is foundopenab-claude,openab-codex,openab-gemini,openab-copilot,openab-opencode,openab-pi,openab-mimocode)The
0.10.0release note will carry the security section, the #1564 migration step, and the deletion notice with this date. Users still onghcr.io/openabdev/openab-<agent>should migrate toghcr.io/openabdev/openab:<tag>-<agent>before then (seedocs/image-tags.md).Step 3 — PRs: @antigenius0910, the three PRs (Node ARG pin + smoke tests,
node-security-check.yml, RELEASING.md runbook + SECURITY.md) are still yours if you want them. Please reply here by 2026-10-24 end of day (UTC). If we don't hear back by then, maintainers will pick them up. No problem either way.chaodu-obk commentedon Oct 23, 2026
0.10.0-beta.6Node verification: passed. The Build Operator run completed successfully: https://github.com/openabdev/openab/actions/runs/39883871537NODE_VERSIONwas read from the published image configs through an anonymous GHCR request, for both linux/amd64 and linux/arm64:beta-claude,0.10.0-beta.6-claudebeta-codexbeta-copilotbeta-geminibeta-mimocodebeta-opencodebeta-pibeta-kimi,0.10.0-beta.6-kimibeta-kiro(control, no Node)All images were built on 2026-10-23, between 01:38 and 01:40 UTC. No
no_cachere-run was needed.stable-*stays on Node 22.23.1 until0.10.0is promoted, planned for 2026-10-30.chaodu-obk commentedon Oct 23, 2026
pre-beta-*and downstreamopenab-ptyimages are now on the patched Node. Each tag was checked for both linux/amd64 and linux/arm64.openab:pre-beta-<agent>openab-pty:pre-beta-<variant>openab-pty:nightly-<variant>Before this,
openab:pre-beta-*had not been rebuilt since 2026-10-03 (99c11ec).openab-ptybuilds every imageFROM openab:pre-beta-<variant>, including nightly, so all of its images were on 22.23.3 as well. The root cause is the pre-beta schedule gate, which compared against a 70-minute window while GitHub delivers the hourly schedule only every ~4–5 hours. The fix is in #1573. The daily check in #1571 should cover these channels too (see #1571 (comment)).docs(release): address review on the security release runbook
chore(ci): add daily node-security-check workflow (#1571)
chore(ci): harden node-security-check per review suggestions
chore(docker): drop hard-coded Node pin assertions
chore(docker): make node_base_arg.sh the only Node FROM parser
chore(docker): pin Node.js base image via NODE22_VERSION/NODE24_VERSI…
docs(release): add SECURITY.md and base image security runbook (#1572)
chore(ci): harden node-security-check per #1571 review (#1574)