You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#50 added npm install -g --ignore-scripts npm@11.19.1 mid-RUN in the Dockerfile to clear 8 CVEs in npm's vendored dependencies (tar, brace-expansion, ip-address). It works, but it creates a fourth pin category: not a pins/*.env fragment, not an ARG-with-bump-command like NODE_VERSION/TASK_VERSION, and not in update_pins.py's TOOLS registry.
Raised in review on #50 (comment); confirmed against the code:
pins-updater.yml will never bump it — the weekly refresh only walks TOOLS.
It skips the soak gate and the npm audit signatures check that claude-code, openspec and pnpm all get, since those come from --list-npm-tools. It is currently the only npm package in the image with no provenance verification.
Nothing enforces the Dockerfile comment's "drop the extra install once NodeSource catches up".
Why it matters now
#49 adds a blocking Trivy gate on HIGH/CRITICAL findings that have a fix available. When npm 11.19.1 accrues one — and it will — the gate goes red with no automated path back to green: no reminder says the pin is stale, and no refresh will move it. Someone has to notice the CVE and hand-edit a version buried in the middle of a RUN chain.
Options
A. Make npm a tracked pin. The npm-kind machinery already exists for pnpm, so this is small: a TOOLS entry, a fragment_lines branch emitting NPM_VERSION, a pins/npm.env, and sourcing it in the Dockerfile the way the pnpm layer does. That earns the weekly bump, the soak window, the signature audit and the version assertion for free.
This touches version-pin-refresh — its enumerated npm tools and its manual-pin reminder requirements — so it needs an OpenSpec change. That is the reason it wasn't folded into #49 or #50: both were clearing live vulnerabilities, and blocking them behind a larger spec change would have been the wrong trade.
B. Minimum viable. Keep it manual but promote it to an ARG at the top of the Dockerfile with the bump command in the comment, matching the NODE_VERSION and TASK_VERSION blocks, so it is discoverable as a manual pin instead of buried mid-RUN. Cheaper, but still leaves it outside the soak gate, the signature audit and the version assertion.
A is the better end state; B is worth doing immediately if A isn't scheduled soon.
One correction worth recording
The review suggested 11.x over the latest 12.0.2 was presumably deliberate for Node 24 compatibility. It isn't: npm 12.0.2 declares engines.node of ^22.22.2 || ^24.15.0 || >=26.0.0, which the image's Node 24.20.0 satisfies. 11.19.1 was simply the minimal version that cleared the CVEs. Whichever option is taken should record the intended major line, because right now nothing does.
Same theme, different blocker — worth doing together, but not a duplicate.
#47 covers task and nodejs: both are manual ARG pins that do get the ⚠ needs your eyes drift reminder, and they stay manual because their apt install sources publish no dates, so update_pins.py's soak gate has nothing to gate on. Its proposal is to supply a second, dated oracle feed.
npm has none of that difficulty. It is an npm-registry package, so the registry's time metadata already provides publish dates, and kind="npm" already exists and works for pnpm. It needs no oracle machinery — just a registry entry and a fragment.
npm is also currently worse off than either of #47's pins: task and nodejs at least surface in the weekly reminder, whereas npm appears in no category at all.
Both land on the same surface — TOOLS, fragment_lines, and the version-pin-refresh spec's enumerated npm tools and manual-pin reminder requirements — so a single OpenSpec change could reasonably cover all three, with npm as the trivial case.
Problem
#50 added
npm install -g --ignore-scripts npm@11.19.1mid-RUNin the Dockerfile to clear 8 CVEs in npm's vendored dependencies (tar,brace-expansion,ip-address). It works, but it creates a fourth pin category: not apins/*.envfragment, not anARG-with-bump-command likeNODE_VERSION/TASK_VERSION, and not inupdate_pins.py'sTOOLSregistry.Raised in review on #50 (comment); confirmed against the code:
pins-updater.ymlwill never bump it — the weekly refresh only walksTOOLS.update_pins.py --list-tools.npm audit signaturescheck thatclaude-code,openspecandpnpmall get, since those come from--list-npm-tools. It is currently the only npm package in the image with no provenance verification.Why it matters now
#49 adds a blocking Trivy gate on HIGH/CRITICAL findings that have a fix available. When npm 11.19.1 accrues one — and it will — the gate goes red with no automated path back to green: no reminder says the pin is stale, and no refresh will move it. Someone has to notice the CVE and hand-edit a version buried in the middle of a
RUNchain.Options
A. Make npm a tracked pin. The npm-kind machinery already exists for
pnpm, so this is small: aTOOLSentry, afragment_linesbranch emittingNPM_VERSION, apins/npm.env, and sourcing it in the Dockerfile the way thepnpmlayer does. That earns the weekly bump, the soak window, the signature audit and the version assertion for free.This touches
version-pin-refresh— its enumerated npm tools and its manual-pin reminder requirements — so it needs an OpenSpec change. That is the reason it wasn't folded into #49 or #50: both were clearing live vulnerabilities, and blocking them behind a larger spec change would have been the wrong trade.B. Minimum viable. Keep it manual but promote it to an
ARGat the top of the Dockerfile with the bump command in the comment, matching theNODE_VERSIONandTASK_VERSIONblocks, so it is discoverable as a manual pin instead of buried mid-RUN. Cheaper, but still leaves it outside the soak gate, the signature audit and the version assertion.A is the better end state; B is worth doing immediately if A isn't scheduled soon.
One correction worth recording
The review suggested 11.x over the latest 12.0.2 was presumably deliberate for Node 24 compatibility. It isn't: npm 12.0.2 declares
engines.nodeof^22.22.2 || ^24.15.0 || >=26.0.0, which the image's Node 24.20.0 satisfies. 11.19.1 was simply the minimal version that cleared the CVEs. Whichever option is taken should record the intended major line, because right now nothing does.Relationship to #47
Same theme, different blocker — worth doing together, but not a duplicate.
#47 covers
taskandnodejs: both are manualARGpins that do get the⚠ needs your eyesdrift reminder, and they stay manual because their apt install sources publish no dates, soupdate_pins.py's soak gate has nothing to gate on. Its proposal is to supply a second, dated oracle feed.npm has none of that difficulty. It is an npm-registry package, so the registry's
timemetadata already provides publish dates, andkind="npm"already exists and works forpnpm. It needs no oracle machinery — just a registry entry and a fragment.npm is also currently worse off than either of #47's pins:
taskandnodejsat least surface in the weekly reminder, whereas npm appears in no category at all.Both land on the same surface —
TOOLS,fragment_lines, and theversion-pin-refreshspec's enumerated npm tools and manual-pin reminder requirements — so a single OpenSpec change could reasonably cover all three, with npm as the trivial case.