Skip to content

npm's version pin sits outside the pin machinery, so nothing will bump it #51

Description

@dtump

Problem

#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.
  • The runtime version assertion from ci: assert every pinned CLI reports its pinned version, not just claude-code #48 doesn't cover it, because that loop is driven by update_pins.py --list-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.

Relationship to #47

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.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    tech-debtInternal code-quality / maintainability

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions