GHSA-qrv3-253h-g69c - pnpm configDependencies symlink traversal

pnpm accepts package names from env lockfile configDependencies and uses those names when creating config dependency symlinks under node_modules/.pnpm-config. A malicious repository can commit a crafted pnpm-lock.yaml with traversal-shaped config dependency names and cause pnpm install to create symlinks outside the intended directory, even with --ignore-scripts.

This is a source supply-chain filesystem write primitive triggered by installing an untrusted or compromised repository.

When to use it

Use this recipe when a repository pins pnpm, runs pnpm install in CI, devcontainers, release jobs, SBOM builders, or developer setup, and may install untrusted branches, templates, plugins, examples, customer packages, or marketplace content. It is most important when install jobs run with publish, deploy, signing, cloud, or repository-write credentials.

Use it to upgrade pnpm and harden lockfile/symlink policy. Do not use it to create symlinks outside the repository during validation.

Inputs

  • packageManager, Corepack config, GitHub Actions, Dockerfiles, devcontainers, scripts, release workflows, SBOM builders, documentation, and prebuilt images that pin or install pnpm.
  • Resolved pnpm versions in local, CI, image, and developer environments.
  • pnpm-lock.yaml files and env lockfile configDependencies, including whether untrusted PRs, templates, examples, or marketplace content can modify them before install.
  • CI secret exposure during install: package publish tokens, signing keys, deploy keys, cloud credentials, repository tokens, and cache write tokens.
  • Existing lockfile validation, path-boundary checks, symlink creation helpers, and trust-boundary cache policies.

Affected versions

  • Vulnerable: pnpm <10.34.4
  • Vulnerable: pnpm >=11.0.0, <11.8.0
  • Fixed: pnpm 10.34.4+ or pnpm 11.8.0+
  • Affected surface: env lockfile configDependencies symlink creation

Indicator-of-exposure

  • The repository pins or downloads vulnerable pnpm versions in Corepack, package-manager metadata, CI setup, devcontainers, Dockerfiles, or release workflows.
  • CI installs untrusted pull requests, template repositories, plugins, examples, customer packages, or marketplace content.
  • Build jobs run pnpm install with workspace, release, cache, deploy, or publish credentials present.
  • Lockfile policy allows env lockfile configDependencies from untrusted branches without review.

Quick checks:

rg -n "packageManager.*pnpm|corepack|pnpm/action-setup|pnpm-lock.yaml|configDependencies|PNPM_HOME|pnpm install" .
pnpm --version

Windows:

rg -n "packageManager.*pnpm|corepack|pnpm/action-setup|pnpm-lock.yaml|configDependencies|PNPM_HOME|pnpm install" .
pnpm --version

Remediation strategy

  • Upgrade pnpm to 10.34.4+ or 11.8.0+ in every pinned environment.
  • Reject env lockfile config dependency names containing absolute paths, ./.., backslashes, platform separators, or invalid npm package names.
  • For any repository-owned tooling that creates symlinks from lockfile names, resolve the final path and prove it remains under the intended root.
  • Run untrusted installs without publish, deploy, signing, cloud, or repository write credentials.

The prompt

Model context: this prompt was generated by GPT 5.5 Extra High reasoning.

You are remediating GHSA-qrv3-253h-g69c in pnpm. Traversal-shaped
`configDependencies` names in an env lockfile can create symlinks outside
`node_modules/.pnpm-config`. Produce exactly one output:

- A reviewer-ready PR/change request that upgrades pnpm, hardens lockfile and
  install policy, adds safe path-boundary checks, and documents operator
  cleanup, or
- TRIAGE.md if this repository does not control pnpm install tooling or
  affected CI/developer environments.

## Rules

- Scope only GHSA-qrv3-253h-g69c and directly related pnpm install,
  configDependencies, lockfile, symlink, CI, and release controls.
- Treat package publish tokens, signing keys, deploy keys, cloud credentials,
  repository tokens, lockfiles, and caches as sensitive.
- Do not install attacker-controlled packages or create symlinks outside the
  repository for validation.
- Do not auto-merge.

## Steps

1. Inventory every pnpm pin and installer controlled here: `packageManager`,
   Corepack config, GitHub Actions, Dockerfiles, devcontainers, scripts,
   release workflows, SBOM builders, and documentation.
2. Determine whether any environment resolves to `pnpm <10.34.4` or
   `>=11.0.0, <11.8.0`.
3. Search `pnpm-lock.yaml` files for `configDependencies` and review whether
   lockfile changes from untrusted branches can run in CI.
4. If this repository does not control pnpm install tooling, stop with
   `TRIAGE.md` naming the owning platform and required fixed versions.
5. Upgrade every pnpm pin to `10.34.4+` or `11.8.0+`.
6. Add dependency policy checks that reject vulnerable pnpm versions in
   package-manager metadata, CI setup, and container images.
7. Add lockfile validation for env `configDependencies` names:
   - reject absolute paths;
   - reject `.` or `..` path components;
   - reject backslashes and platform path separators;
   - require valid npm package names.
8. Ensure untrusted installs run without package publish, signing, deploy,
   cloud, or repository-write credentials.
9. Add a PR body section named `GHSA-qrv3 operator actions` covering:
   - pnpm versions before and after;
   - which install environments were updated;
   - whether untrusted PRs or templates can control lockfiles;
   - whether caches or workspaces need cleanup;
   - validation that passed.
10. Run available validation: package manager version checks, lockfile
    validation, install dry run on trusted content, tests, build, and
    dependency/security scans.
11. Use PR title:
    `fix(sec): remediate pnpm configDependencies symlink traversal`.

## Stop conditions

- No pnpm install path, CI job, image, or developer environment is controlled
  by this repository.
- Upgrade requires a broader package-manager migration decision.
- Verification would require installing malicious packages or writing outside
  the repository.
- Validation fails for unrelated pre-existing reasons; document those failures.

Verification - what the reviewer looks for

  • No controlled environment pins vulnerable pnpm versions.
  • Lockfile validation rejects traversal-shaped configDependencies.
  • Untrusted installs are separated from publish, signing, deploy, and cloud credentials.

Watch for

  • Updating local packageManager while CI uses an older pnpm action or prebuilt image.
  • Trusting --ignore-scripts as sufficient protection.
  • Checking only package manifests while env lockfile entries remain unreviewed.

Output contract

Return one of:

  • A reviewer-ready PR/change request that upgrades every controlled pnpm pin to 10.34.4+ or 11.8.0+, adds lockfile validation for traversal-shaped configDependencies, separates untrusted installs from high-value credentials, refreshes generated artifacts, and documents cache/workspace cleanup.
  • TRIAGE.md when no controlled pnpm install path, CI job, image, developer environment, lockfile policy, or generated artifact exists.

The output must list pnpm versions before/after, install environments updated, whether untrusted inputs can control lockfiles, validation commands, caches or workspaces to clean, and any temporary containment. It must not install malicious packages, create symlinks outside the repository, rely on --ignore-scripts alone, or leave install jobs with unnecessary publish/deploy credentials.

References