Skip to content
Back to skills

Pnpm Release Age Gate

ASecurity

Configure pnpm's minimumReleaseAge gate (7-day default, 10-day high-sensitivity) plus blockExoticSubdeps for workspace-scope dep-source enforcement. Includes Corepack detection and lockfile-caveat warning.

  • 207 stars
  • 0 votes
  • 0 copies
  • 6 views
  • Added May 27, 2026
data-aigobashnodenodejsgitsecurity

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned May 27, 2026

npx -y skills add jmagly/aiwg --skill pnpm-release-age-gate --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Pnpm Release Age Gate?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Pnpm Release Age Gate
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/jmagly-pnpm-release-age-gate/badge)](https://www.skillsdirectory.com/skills/jmagly-pnpm-release-age-gate)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
namespace: aiwg
name: pnpm-release-age-gate
platforms: [all]
description: Configure pnpm's minimumReleaseAge gate (7-day default, 10-day high-sensitivity) plus blockExoticSubdeps for workspace-scope dep-source enforcement. Includes Corepack detection and lockfile-caveat warning.
---

# pnpm-release-age-gate

Use this skill when a user has chosen pnpm as their package manager
and wants to apply the same release-age-gate hardening that
`npm-release-age-gate` provides for npm. pnpm is often the **preferred
baseline** for new projects because `minimumReleaseAge` AND
`blockExoticSubdeps` can be enforced at the workspace level — npm
has no equivalent for the latter.

## Triggers

- "pnpm release age gate"
- "pnpm minimumReleaseAge"
- "pnpm blockExoticSubdeps"
- "pnpm supply chain hardening"
- "configure pnpm 7 day gate"

## Prerequisites

- pnpm v9.0+ installed (`pnpm --version`)
- `package.json` exists at repo root

If pnpm is below v9.0, the skill should refuse to proceed and direct
the user to upgrade — `minimumReleaseAge` was introduced in v9.0 and
older versions silently ignore it.

## Configuration paths — pick one based on workspace shape

### Option A — Single-package repo (most common)

Add the gate to `.npmrc` at repo root:

```ini
# Refuse dependency versions published less than 7 days ago.
# pnpm interprets the value in MINUTES. 10080 = 7 days; 14400 = 10 days.
# Defends against newly-published malicious versions.
minimum-release-age=10080

# Reject git+, tarball-URL, file:, link: sources — these bypass
# registry signature verification (companion to npm-supply-chain-audit
# dep-source policy).
block-exotic-subdeps=true
```

### Option B — Multi-package workspace

Add the gate to `pnpm-workspace.yaml`:

```yaml
packages:
  - 'packages/*'
  - 'apps/*'

# Workspace-scope release-age enforcement.
# Value is in MINUTES. 10080 = 7 days; 14400 = 10 days.
minimumReleaseAge: 10080

# Reject non-registry dep sources fleet-wide.
blockExoticSubdeps: true
```

Workspace-scope is the pnpm advantage over npm — every nested package
inherits the gate without per-package config.

### Option C — Operator-wide via pnpm global config

```bash
pnpm config set minimum-release-age 10080  # minutes — 7 days
pnpm config set block-exotic-subdeps true
```

Use this only when the entire dev machine should apply the gate
across all projects. Per-repo config (Option A or B) is preferred —
it travels with the repo and works in CI without machine setup.

## Unit conversion reference

pnpm uses **minutes** for `minimumReleaseAge`:

| Days | Minutes value |
|---|---|
| 1 | `1440` |
| 7 (recommended default) | `10080` |
| 10 (high-sensitivity profile) | `14400` |
| 14 | `20160` |
| 30 | `43200` |

This differs from npm (`min-release-age` in **days**) and Bun
(`install.minimumReleaseAge` in **seconds**). Document the unit
inline when committing the config so future readers don't misread it.

## Lockfile caveat

The gate must be active **before** `pnpm install` or `pnpm update`
resolves dependencies. If the existing `pnpm-lock.yaml` was generated
without the gate, the gate is checked on the NEXT resolution pass —
not retroactively against the lockfile.

To apply the gate retroactively:

```bash
# Force re-resolution with the gate active
rm pnpm-lock.yaml
pnpm install
```

This is destructive to existing pins and may pull in newer
intermediate versions. Coordinate with the team before running.

## Corepack detection

Check whether the project pins a pnpm version via Corepack:

```bash
node -p "require('./package.json').packageManager"
```

Output like `pnpm@9.15.0` means Corepack will use that exact version
in CI. The skill should:

1. Confirm the pinned version is ≥ v9.0 (else flag — gate is silently ignored)
2. Document the pinned version in the audit output
3. Suggest a Corepack pin if the project doesn't have one yet:
   ```bash
   corepack use pnpm@latest
   # writes packageManager to package.json
   ```

## Override policy

Genuine emergency overrides:

```bash
# One-off install bypassing the gate
pnpm install <pkg>@<version> --ignore-min-release-age

# Permanently allow a specific package (rare; record rationale in
# a SECURITY-OVERRIDE.md or equivalent)
```

Document every override with reason + sunset date. Overrides should
be reviewed quarterly.

## CI integration

Add a verification step to the publish/build workflow:

```yaml
- name: Verify pnpm gate active
  run: |
    set -euo pipefail
    AGE=$(pnpm config get minimum-release-age 2>/dev/null || echo "0")
    EXOTIC=$(pnpm config get block-exotic-subdeps 2>/dev/null || echo "false")
    if [ "$AGE" -lt 10080 ] || [ "$EXOTIC" != "true" ]; then
      echo "✗ pnpm gate not configured to baseline (minimumReleaseAge≥10080, blockExoticSubdeps=true)"
      exit 1
    fi
    echo "✓ pnpm gate active: $AGE minutes, blockExoticSubdeps=$EXOTIC"
```

## What to inspect during review

- `.npmrc` OR `pnpm-workspace.yaml` for `minimumReleaseAge` and `blockExoticSubdeps`
- `package.json` `packageManager` field for Corepack pin
- CI workflow has the verification step above
- `pnpm-lock.yaml` was generated AFTER the gate was committed (timestamp check)

## Output format

When auditing an existing pnpm project, produce a structured report
at `.aiwg/security/working/pnpm-release-age-audit.md`:

```markdown
# pnpm Release-Age Gate Audit

**pnpm version**: <version>  (Corepack pinned: yes/no)
**Workspace shape**: single-package / multi-package
**Gate active**: yes (10080 min) / yes (custom: <value>) / no
**blockExoticSubdeps**: true / false / unset

## Findings

### <severity> — <description>

- File: <path>
- Issue: <what's wrong>
- Fix: <exact change>

## Clean Checks

- ...

## Recommendations

- ...
```

## See Also

- [`npm-release-age-gate` skill](../npm-release-age-gate/SKILL.md) — npm equivalent
- [`yarn-release-age-gate` skill](../yarn-release-age-gate/SKILL.md) — Yarn equivalent
- [`bun-release-age-gate` skill](../bun-release-age-gate/SKILL.md) — Bun equivalent
- [`npm-supply-chain-audit` skill](../npm-supply-chain-audit/SKILL.md) — companion audit
- [`supply-chain-hardening-quickstart` skill](../supply-chain-hardening-quickstart/SKILL.md) — orchestrator

## References

- pnpm `minimumReleaseAge`: <https://pnpm.io/settings#minimumreleaseage>
- pnpm `blockExoticSubdeps`: <https://pnpm.io/settings#blockexoticsubdeps>
- pnpm workspace settings: <https://pnpm.io/pnpm-workspace_yaml>
- Corepack: <https://github.com/nodejs/corepack>

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.