Commit Graph
7 Commits
Author SHA1 Message Date
Zoltan Kochan 68445b254a fix: harden dependency verification and package handling (#16613)
Verify configuration dependency registry resolutions before installing
plugins, with independently checked pinned tarballs. Require config dependencies to resolve from a registry and skip
registry verification when the installed config dependencies already match
the lockfile.

Constrain archive and deployment paths and preserve content-addressed files
when streaming package entries. Bound metadata allocation before the archive
parser buffers it, using an opt-in patch to the upstream tar crate. Bound
publishing manifest and README buffers without imposing a total extraction
disk quota.

Bind audit signatures to lockfile integrity, hash ambiguous URL dependency
directory names, and sanitize license terminal output. Preserve dependency
error context and structured fatal logs. Update affected documentation,
release notes, and regression coverage.
2026-10-05 22:09:01 +02:00
Zoltan Kochan 103c4cada2 fix(prepare-package): prevent intermediate symlink traversal in subpath extraction (#16612)
When preparing a git dependency with a `#path:` subpath fragment,
intermediate symlink segments pointing outside the repository checkout
could allow files outside the cloned repository directory to be copied
into the store during package preparation.

Resolve and canonicalize both the repository root and joined paths using
`fs.realpathSync` in `safeJoinPath`, verifying containment within the
cloned checkout. Also add unit tests in TypeScript and Rust (`safe_join_path`)
to ensure traversal through intermediate symlinks is rejected.

Fixes https://github.com/pnpm/tasks/issues/82
2026-10-05 19:44:41 +02:00
Zoltan Kochan 4edeef9176 style(ts): port the perfectionist lint rules to ESLint (#16415)
Add TypeScript ports of the perfectionist rules that the Rust workspace
enforces through dylint.toml to @pnpm/eslint-config, with the same limits,
and fix every finding that needs no refactor.

The size and shape rules (function length, cognitive complexity, nesting,
local bindings, file length) are enforced for packages that already meet
them. The packages that do not are listed in PENDING_SIZE_AND_SHAPE_REFACTOR
in eslint.config.mjs and are refactored in follow-up changes.

The custom rules mirror perfectionist's semantics rather than reusing
sonarjs or max-lines-per-function, so that one limit means the same thing
in both codebases: a closure is a level of the body that contains it, a
nested function declaration is measured on its own, and a test-framework
callback plays the role of a #[test] function.

Bugs found and fixed along the way:
- a registry error body cut at exactly 64 KiB lost its truncation marker
- removing a dependency could leave dangling .bin shims
- constructor/__proto__ names crashed the projects graph, were skipped by
  the injected-deps syncer, and were dropped from writeWantedLockfile's
  returned lockfile

The CI chunk runner learns to run the node:test suite of the ESLint
config package.
2026-09-30 15:10:08 +02:00
Zoltan Kochan 360afab03f fix(prepare-package): prepare a lockfile-less pnpm workspace with pnpm (#16301)
preferred-pm recognized pnpm only by a pnpm-lock.yaml, so a git-hosted
dependency that is a pnpm workspace without a committed lockfile fell
back to npm. npm then honoured the dependency's own .npmrc settings,
such as ignore-scripts, and could skip the build.

preferred-pm 5.0.1 also looks for pnpm-workspace.yaml once no lockfile
in the package directory names a package manager. That matches the
order the v12 git fetcher uses since pnpm/pnpm#15660, where a lockfile
still wins over the workspace file.

The test asserts which lockfile the prepare step leaves behind. It only
fails without the fix when no ancestor of the test directory holds a
pnpm-lock.yaml, because preferred-pm searches parent directories for
one.

Closes pnpm/pnpm#14011
2026-09-28 00:28:28 +02:00
Altay 7c1b501d2d fix(git-fetcher): skip unapproved builds while preparing a git dependency (#15465)
A git-hosted dependency that has to be built is prepared by running its
package manager's install in a temporary checkout. With strictDepBuilds on
by default, that nested pnpm install failed with ERR_PNPM_IGNORED_BUILDS as
soon as one of the dependency's own dependencies had a build script, and
nobody can approve builds in that checkout. The outer install then failed
with ERR_PNPM_PREPARE_PACKAGE.

The prepare scripts now run with pnpm_config_strict_dep_builds=false. No
additional build runs: unapproved builds in the checkout are skipped and
reported, as they are without strictDepBuilds.

Closes pnpm/pnpm#9764
2026-09-26 03:11:21 +02:00
Zoltan Kochan f922cba3f1 fix(install): skip explicitly denied git preparation (#15149)
Distinguish an explicit denial from an undecided Git dependency build.
Install source files when preparation is denied, while retaining the
approval error for dependencies without a recorded decision.

Carry skipped-preparation state through the fetchers and in-memory cache.
Select the existing unprepared store key for denied builds so subsequent
approvals prepare the dependency and denials do not reuse prepared output.

Apply the behavior to both CLI versions and to cloned Git repositories
and Git-hosted tarballs. Cover explicit denials, policy transitions,
shared-store approval enforcement, and initially unknown package names.

Closes pnpm/pnpm#10522.
2026-09-20 11:25:24 +02:00
Zoltan Kochan fc2f33912e refactor: move the TypeScript pnpm CLI into a pnpm11/ directory (#12537)
The TypeScript pnpm CLI freezes at v11; pnpm 12 will be the Rust pacquet
port. To make that split legible, all TypeScript source, test, and build
directories move under a new top-level pnpm11/ directory. The name states
the version boundary rather than implying a behavioral fork, since the two
stacks are meant to behave identically.

Scope is source-only: the shared workspace root stays at the repo root.
pnpm-workspace.yaml, package.json, pnpm-lock.yaml, .pnpmfile.cjs,
.meta-updater, __patches__, .changeset, .husky, and the lint/spell configs
remain in place, so one pnpm workspace and one Cargo workspace still span
all three products. pnpr/client and pacquet/tasks/registry-mock stay as
cross-product workspace members.

Rewiring the move required:
- pnpm-workspace.yaml globs prefixed with pnpm11/
- root package.json script paths, eslint.config.mjs, tsconfig.lint.json,
  .gitignore, and CODEOWNERS updated
- .meta-updater/src/index.ts literals repointed (pnpm11/pnpm/package.json,
  pnpm11/__utils__, pnpm11/__typings__, and the main package directory)
- regenerated every moved package's repository/homepage URL via meta-updater
- pnpm11/pnpm/bundle-deps.ts and __utils__/scripts/src/typecheck-only.ts
  climb one more level to reach the repo root

.meta-updater stays at the repo root because @pnpm/meta-updater resolves
its config at <cwd>/.meta-updater/main.mjs.

TS CI (.github/workflows/ci.yml) now only runs when pnpm11/-relevant paths
change, via a dorny/paths-filter changes job plus a TS CI / Success
aggregate gate; branch protection should require only that gate.
2026-06-20 14:36:25 +02:00