Repository navigation
v2.4.1
Security
-
gateway.update_serverno longer installs and executes a registry package
derived from a misparsed command. The update probe is built from the parsed
package name —npx -y {name}@latest --help— andnpx -yinstalls without
prompting. A server configured asnpm run mcpnames a script in the
localpackage.json, not a registry package, but the parser returned it as
one, so pmcp fetched and ran whatever occupied that name on the public
registry. Short generic script names (run,start,dev,mcp) are
exactly the kind that can be registered and waited on.npm package detection is now an allowlist: only
exec,x,install,
i,addanddlxput a registry package in the next position. Every other
subcommand —run,start,test,stop,restart,run-script,init,
create— and every misspelling of one reports no recoverable package
identity, andupdate_serverrefuses on that before constructing any
probe. That is the same rule the identity gate follows: cannot confirm, so do
not act on a guess.An allowlist rather than a denylist of script runners, because the
consequence of being wrong is asymmetric: failing closed costs only the
ability to auto-update a server launched by an unusual form, while failing
open costs arbitrary package execution. (npm create fooalso shows why
synthesising a name is not safe: npm resolves it to the packagecreate-foo,
sofoonames a different package than the one npm would run.)Reaching this required a server configured with an affected form and an
operator invokinggateway.update_serveron it; it was not remotely
triggerable.npx -y runstill resolves normally — the refusal is scoped to
npm subcommands whose operand is not a package, not to those names.
Fixed
-
Two different packages no longer share one identity for common
dockerand
npmcommand forms. 2.4.0's identity gate decides whether a cached
description still describes the configured package by comparing the name
detect_package_typereturns, so a name that was stable across two different
packages was read as a positive confirmation — and the freshness
short-circuit went on serving the wrong package's tool descriptions.Two independent causes, both closed:
- Docker references split on the first
:, soregistry:5000/old-image
andregistry:5000/new-imageboth resolved to the imageregistry— the
registry host, not an image at all. A colon only introduces a tag when it
appears in the final path segment; before the last/it is a registry
host:port. The correct rule already existed in this module as
_docker_image_tag, so the fix adds its paired complement rather than a
second, divergent implementation of the same rule. npmsubcommands were taken as the package name, sonpm exec old-pkg
andnpm exec new-pkgboth resolved toexec. A leading subcommand
(exec,x,run,install,i,add,create,dlx) is now skipped
— once, and only fornpm, sonpm install istill finds the real package
iandnpx -y execstill finds a package genuinely namedexec.
Affected servers refresh once. A docker server on a
host:portregistry
or annpm execserver now has a different package identity than the one
its cache entry recorded, so that entry fails the identity check once and is
regenerated — the same one-time migration 2.4.0'spackage_typeaddition
caused. - Docker references split on the first
-
A docker digest is now recognised as the pin it is.
gateway.update_server
read the tag from the whole reference, soimg@sha256:abcreported a pin of
abc— a fragment of the digest presented as a version — and
img:1.2@sha256:abcreported1.2@sha256:abcinstead of a usable value. A
digest is the tightest pin docker offers, so it is now reported whole and
checked before the tag:img@sha256:…,img:1.2@sha256:…and
img:latest@sha256:…all report the digest. That last form matters — a
latesttag must not discard a real digest pin. Previously such a server
could be "updated": pmcp would pullimage:latest, restart the unchanged
digest-pinned configuration, and record the registry's newest digest while
still running the old immutable image. -
A version pin on an
npm execserver is now detected. Pin detection
shares its argument scan with package detection, so it inherited the
subcommand bug:npm exec pkg@1.2scanned toexec, which carries no
version suffix, and a real pin was reported as unpinned.This narrows #180 rather than closing it. Package identity
is still collapsed wherever a flag's value is taken as the package name —
docker run --env-file X <image>,docker run --mount <spec> <image>,
npm exec --package=<pkg>, and theuvx/pip/cargoequivalents. Those are
tracked on #182, and #183 tracks a related but
more serious consequence of a misparse.