Skip to content

[pull] main from pnpm:main#332

Merged
pull[bot] merged 3 commits into
dwongdev:mainfrom
pnpm:main
Jun 18, 2026
Merged

[pull] main from pnpm:main#332
pull[bot] merged 3 commits into
dwongdev:mainfrom
pnpm:main

Conversation

@pull

@pull pull Bot commented Jun 18, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

zkochan and others added 3 commits June 18, 2026 00:46
…tries (#12471)

Port the GHSA-j2hc-m6cf-6jm8 fix (#12296) to pacquet.

When pnpm auto-switches to the version requested by `packageManager` /
`devEngines.packageManager`, the bootstrap (`pnpm` / `@pnpm/exe`) must be
resolved through trusted registries only. Pacquet was resolving it through
`config.resolved_registries()`, which a malicious repository controls via
the workspace `.npmrc` or `pnpm-workspace.yaml` `registries:` block.

Add `Config::package_manager_bootstrap`, built in `Config::current()` from a
trusted-only fold of the URL-scoped env, `auth.ini`, and user `.npmrc`
sources (the project `.npmrc` is excluded), reusing the existing
registry/proxy/TLS/auth application logic. It defaults to the public npm
registry, and `PNPM_CONFIG_REGISTRY` still overrides the default because it
is user-controlled.

`EnvInstallerContext::for_package_manager` routes only the package-manager
bootstrap path (`sync_package_manager_dependencies`) through this trusted
config; project `configDependencies` resolution keeps the project
registries, matching the narrow scope of the upstream TypeScript fix.
…ile (#12470)

Config dependency names and versions are read from the committed env lockfile
(pnpm-lock.yaml) and the legacy inline-integrity format in pnpm-workspace.yaml,
and both become path segments of the directories pnpm creates during install
(node_modules/.pnpm-config/<name> and the global virtual store's
<name>/<version>/<hash>). They were used unvalidated, so a malicious repository
could commit a traversal-shaped name (../../PWNED) or version (../../../PWNED)
and make `pnpm install` create symlinks or write package files outside those
roots — triggered on install, even with --ignore-scripts.

Add verifyEnvLockfile, an offline structural gate that validates every config
dependency and optional-subdependency name (must be a valid npm package name)
and version (must be an exact semver version) before any path is built from it.
It runs at the install boundary and, through a single writeVerifiedEnvLockfile
seam, before the env lockfile is ever persisted, so an invalid entry is rejected
with no write side effect. __proto__ names are rejected too (the validation
accumulators use null-prototype objects so the key can't slip past Object.keys).

The same fix and structure land in pacquet to keep the two stacks in sync.

Fixes GHSA-qrv3-253h-g69c.
…, fail_timeout, cache) (#12375)

Add verdaccio's per-uplink tuning knobs to pnpr's proxy uplinks, parsed
from the same config.yaml shape verdaccio uses:

- maxage:       per-uplink packument freshness window; overrides the
                global packument_ttl when set, otherwise defers to it.
- timeout:      per-request deadline applied to every upstream fetch
                (default 30s).
- max_fails /   circuit breaker: after max_fails consecutive failures the
  fail_timeout  uplink short-circuits with a 503 until the fail_timeout
                cooldown lapses, then one probe per window is allowed
                through (defaults 2 / 5m). max_fails: 0 disables it.
- cache:        when false, tarballs stream through without being written
                to the local mirror (default true).

Interval values accept verdaccio's format ("2m", "30s", "1h30m", or a
bare number of seconds, as either a YAML string or a numeric scalar);
an unparsable or out-of-range value is a named InvalidConfig error
rather than a silent fallback or a panic. Defaults match verdaccio
(timeout 30s, max_fails 2, fail_timeout 5m, cache true).

Circuit breaker behavior:
- Only a 5xx or transport error counts as a failure; a non-404 4xx
  (auth / rate-limit / bad request) surfaces verbatim and never opens
  the circuit.
- The half-open probe is gated on the cooldown window, so exactly one
  probe runs per fail_timeout and a cancelled or dropped probe cannot
  stick the breaker open.
- An open breaker reports the configured uplink name, not its upstream
  URL, so the 503 does not disclose internal endpoints.

Part of the verdaccio-parity tracking issue #11973.

Co-authored-by: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Zoltan Kochan <z@kochan.io>
@pull pull Bot locked and limited conversation to collaborators Jun 18, 2026
@pull pull Bot added the ⤵️ pull label Jun 18, 2026
@pull pull Bot merged commit ff9a1cf into dwongdev:main Jun 18, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants