GitHub Advisoryadvisory · npm

GHSA-2phv-j68v-wwqx pnpm vulnerable to Command Injection via environment variable substitution

HIGH Published 2026-01-07 Modified 2026-01-08 Official page ↗
Aliases
CVE-2025-69262
Ecosystem
npm
Packages
pnpm
Severity
High
CVSS vector
CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H
Weaknesses
CWE-78, CWE-94
Reviewed
2026-01-07

Affected packages

• npm pnpm: >= 6.25.0, < 10.27.0 → fixed in 10.27.0

Description

Summary A command injection vulnerability exists in pnpm when using environment variable substitution in `.npmrc` configuration files with `tokenHelper` settings. An attacker who can control environment variables during pnpm operations could achieve remote code execution (RCE) in build environments. Affected Components • Package: pnpm • Versions: All versions using `@pnpm/config.env-replace` and `loadToken` functionality • File: `pnpm/network/auth-header/src/getAuthHeadersFromConfig.ts` - `loadToken()` function • File: `pnpm/config/config/src/readLocalConfig.ts` - `.npmrc` environment variable substitution Technical Details Vulnerability Chain 1. Environment Variable Substitution • `.npmrc` supports `${VAR}` syntax • Substitution occurs in `readLocalConfig()` 2. loadToken Execution • Uses `spawnSync(helperPath, { shell: true })` • Only validates absolute path existence 3. Attack Flow ``` .npmrc: registry.npmjs.org/:tokenHelper=${HELPER_PATH} ↓ envReplace() → /tmp/evil-helper.sh ↓ loadToken() → spawnSync(..., { shell: true }) ↓ RCE achieved ``` Code Evidence `pnpm/config/config/src/readLocalConfig.ts:17-18` ```typescript key = envReplace(key, process.env) ini[key] = parseField(types, envReplace(val, process.env), key) ``` `pnpm/network/auth-header/src/getAuthHeadersFromConfig.ts:60-71` ```typescript export function loadToken(helperPath: string, settingName: string): string { if (!path.isAbsolute(helperPath) || !fs.existsSync(helperPath)) { throw new PnpmError('BAD_TOKEN_HELPER_PATH', ...) } const spawnResult = spawnSync(helperPath, { shell: true }) // ... } ``` Proof of Concept Prerequisites • Private npm registry access • Control over environment variables • Ability to place scripts in filesystem PoC Steps ```bash 1. Create malicious helper script cat > /tmp/evil-helper.sh /tmp/rce-log.txt echo "TOKEN_12345" SCRIPT chmod +x /tmp/evil-helper.sh 2. Create .npmrc with environment variable cat > .npmrc Attack successful ==> File created: /tmp/rce-log.txt ==> Arbitrary code execution confirmed ``` Impact Severity • CVSS Score: 7.6 (High) • CVSS Vector: cvss:3.1/AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H Affected Environments High Risk: • CI/CD pipelines (GitHub Actions, GitLab CI) • Docker build environments • Kubernetes deployments • Private registry users Low Risk: • Public registry only • Production runtime (no pnpm execution) • Static sites Attack Scenarios Scenario 1: CI/CD Supply Chain ``` Repository → Build Trigger → pnpm install → RCE → Production Deploy ``` Scenario 2: Docker Build ```dockerfile FROM node:20 ARG HELPER_PATH=/tmp/evil COPY .npmrc . RUN pnpm install # RCE ``` Scenario 3: Kubernetes ``` Secret Control → Env Variable → .npmrc Substitution → RCE ``` Mitigation Temporary Workarounds Disable tokenHelper: ```ini .npmrc registry.npmjs.org/:tokenHelper=${HELPER_PATH} ``` Use direct tokens: ```ini //registry.npmjs.org/:_authToken=YOUR_TOKEN ``` Audit environment variables: • Review CI/CD env vars • Restrict .npmrc changes • Monitor build logs Recommended Fixes 1. Remove `shell: true` from loadToken 2. Implement helper path allowlist 3. Validate substituted paths 4. Consider sandboxing Disclosure • Discovery: 2025-11-02 • PoC: 2025-11-02 • Report: [Pending disclosure decision] References • Repository: https://github.com/pnpm/pnpm • Affected: `@pnpm/config.env-replace@^3.0.2` • Similar: CVE-2024-53866, CVE-2023-37478 Credit Reported by: Jiyong Yang Contact: [email protected]

Related

Alias · CVE (1)

Weakness · CWE (2)

  • CWE-78 Improper Neutralization of Special Elements used in an OS Command weakness
  • CWE-94 Improper Control of Generation of Code weakness

References