Skip to content

chore: add pnpm package age gate for supply chain mitigation#40

Merged
ms2sato merged 2 commits into
mainfrom
chore/setup-package-age-gate
May 17, 2026
Merged

chore: add pnpm package age gate for supply chain mitigation#40
ms2sato merged 2 commits into
mainfrom
chore/setup-package-age-gate

Conversation

@ms2sato

@ms2sato ms2sato commented May 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a supply-chain age gate so that newly published package versions
(including transitive dependencies) are not installed until they have been
public for 7 days. Most malicious npm releases are detected and removed
from the registry within hours, so this closes the riskiest window.

pnpm v11 reads minimumReleaseAge / engineStrict from
pnpm-workspace.yaml (not .npmrc, which is auth/registry only).

Changed files & values

File Setting Value
pnpm-workspace.yaml minimumReleaseAge 10080 (minutes = 7 days)
pnpm-workspace.yaml engineStrict true
package.json engines.pnpm ">=11.0.0"
package.json packageManager pnpm@11.1.2 (corepack integrity hash)
README.md Documents requirement, corepack, bypass procedure

Scope: pnpm monorepo only (root + packages/* + demo). No npm/yarn/bun
usage in the repo. pnpm-lock.yaml is unchanged — all current deps were
published more than 7 days ago, so nothing downgraded.

Notes for existing members

  • A minimum pnpm version is now enforced. Run corepack enable to pick up
    the pinned pnpm@11.1.2 automatically. With engineStrict, pnpm install
    fails on pnpm < 11.0.0.
  • To take an urgent security fix before the 7-day window, override
    per-command instead of editing config:
    pnpm add <pkg> --config.minimumReleaseAge=0. Record the reason (CVE)
    in the PR/commit.

Follow-up (out of scope)

CI uses pnpm/action-setup@v4; it reads packageManager from
package.json, so it should pick up pnpm 11 automatically — worth confirming
on the first CI run of this PR.

Test plan

  • pnpm config get minimumReleaseAge10080
  • pnpm config get engineStricttrue
  • pnpm --version>= 11.0.0 via corepack
  • pnpm install succeeds with no pnpm-lock.yaml diff
  • CI (Test workflow) passes with pnpm 11

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores

    • Updated minimum pnpm version requirement to 11.0.0+
    • Added supply chain security validation requiring dependencies to be at least 7 days old
    • Enabled stricter pnpm version enforcement during package installation
  • Documentation

    • Updated development guide with new prerequisites and configuration details

Review Change Stack

Delay installing newly published packages (including transitive deps)
until they have been public for 7 days, reducing the window in which a
compromised release can be pulled in. pnpm v11 reads these settings from
pnpm-workspace.yaml, not .npmrc.

- pnpm-workspace.yaml: minimumReleaseAge=10080 (minutes, 7d), engineStrict=true
- package.json: engines.pnpm ">=11.0.0", packageManager pnpm@11.1.2
- README: document version requirement, corepack, and per-command bypass
  for urgent security fixes

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 16, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@ms2sato has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 55 minutes and 33 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a4069dc2-be84-473d-9166-bdec991de523

📥 Commits

Reviewing files that changed from the base of the PR and between 92ff5ea and ff4d632.

📒 Files selected for processing (2)
  • README.md
  • pnpm-workspace.yaml
📝 Walkthrough

Walkthrough

This PR establishes pnpm version pinning to 11.1.2, adds engine enforcement via engines.pnpm >=11.0.0 and engineStrict: true, and introduces supply chain security via a 7-day minimumReleaseAge gate. README documentation explains the prerequisites for contributors and the supply chain security bypass mechanism for urgent fixes.

Changes

pnpm version enforcement and supply chain security

Layer / File(s) Summary
pnpm version enforcement and supply chain security
package.json, pnpm-workspace.yaml, README.md
package.json pins pnpm to 11.1.2 and requires engines.pnpm >=11.0.0; pnpm-workspace.yaml enables engineStrict to enforce version compliance and sets minimumReleaseAge: 10080 to delay package installations for 7 days. README.md documents prerequisite setup with corepack and version verification, and explains the supply chain age gate with override examples for security patches.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A pnpm upgrade hops into view,
Version locked at 11.1.2 for safety true,
Engines enforced, supply chains gated wide,
Seven days to season each dependency's ride,
A rabbit's warren stays secure inside! 🔒

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly summarizes the main change: adding a pnpm package age gate for supply chain mitigation, which matches the core objective of the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/setup-package-age-gate

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@package.json`:
- Line 11: The package.json packageManager entry has an incorrect SHA512
integrity string; update the "packageManager" field to use the official
pnpm@11.1.2 hash by replacing the current sha512... value with the correct
"sha512-QVocwll0cx51RVwUaDcb50xapft2IbUNQFbSIkUWCfEUEvI/1gLmFp8eBgRmZB95hZfhvpYaEGiINqZ7FlaUmQ==",
ensuring the packageManager string remains in the form
"pnpm@11.1.2+<sha512...>".

In `@README.md`:
- Around line 245-248: Update the per-command pnpm flag in the README: replace
the camelCase flag `--config.minimumReleaseAge=0` with the correct kebab-case
`--config.minimum-release-age=0` for both occurrences shown with `pnpm add
<pkg>` and `pnpm install` so the examples use the valid CLI syntax.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2cec2528-82a1-483b-aa94-838581f71b9c

📥 Commits

Reviewing files that changed from the base of the PR and between 4907d63 and 92ff5ea.

📒 Files selected for processing (3)
  • README.md
  • package.json
  • pnpm-workspace.yaml

Comment thread package.json
"version:major": "pnpm -r exec -- npm version major --no-git-tag-version && node -e \"const p=require('./packages/core/package.json'); console.log('v'+p.version)\""
},
"packageManager": "pnpm@10.32.1",
"packageManager": "pnpm@11.1.2+sha512.415a1cc25974731e75455c1468371be74c5aa5fb7621b50d4056d222451609f11412f23fd602e6169f1e060466641f798597e1be961a10688836a67b16569499",

@coderabbitai coderabbitai Bot May 16, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify pnpm@11.1.2 exists and check the SHA512 hash

# Fetch the npm registry metadata for pnpm@11.1.2
curl -s https://registry.npmjs.org/pnpm/11.1.2 | jq -r '.dist.shasum, .dist.integrity'

# Also check the latest pnpm version to see if 11.1.2 is current
curl -s https://registry.npmjs.org/pnpm/latest | jq -r '.version'

Repository: contedra/toolkit

Length of output: 204


The SHA512 hash in the packageManager field is incorrect and must be updated.

pnpm@11.1.2 is a valid, current release. However, the integrity hash in package.json (sha512.415a1cc25974731e75455c1468371be74c5aa5fb7621b50d4056d222451609f11412f23fd602e6169f1e060466641f798597e1be961a10688836a67b16569499) does not match the official npm registry hash (sha512-QVocwll0cx51RVwUaDcb50xapft2IbUNQFbSIkUWCfEUEvI/1gLmFp8eBgRmZB95hZfhvpYaEGiINqZ7FlaUmQ==). Corepack will fail to validate and install pnpm with this incorrect hash.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 11, The package.json packageManager entry has an
incorrect SHA512 integrity string; update the "packageManager" field to use the
official pnpm@11.1.2 hash by replacing the current sha512... value with the
correct
"sha512-QVocwll0cx51RVwUaDcb50xapft2IbUNQFbSIkUWCfEUEvI/1gLmFp8eBgRmZB95hZfhvpYaEGiINqZ7FlaUmQ==",
ensuring the packageManager string remains in the form
"pnpm@11.1.2+<sha512...>".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

False positive — no change needed. The packageManager field in
package.json uses corepack's hash format, which is the SHA-512 digest
hex-encoded (pnpm@11.1.2+sha512.<hex>). The npm registry's
dist.integrity is the same SHA-512 digest base64-encoded (SRI:
sha512-<base64>). They are not different hashes, just different
encodings of the same digest.

Verified: base64-decoding the registry value
QVocwll0cx51RVwUaDcb50xapft2IbUNQFbSIkUWCfEUEvI/1gLmFp8eBgRmZB95hZfhvpYaEGiINqZ7FlaUmQ==
yields exactly
415a1cc25974731e75455c1468371be74c5aa5fb7621b50d4056d222451609f11412f23fd602e6169f1e060466641f798597e1be961a10688836a67b16569499,
which matches the value in package.json. This string was generated by
corepack use pnpm@11.1.2, so corepack will validate it correctly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

@ms2sato, you're absolutely right — I apologize for the false positive. My comparison was flawed: I compared corepack's hex-encoded SHA-512 digest against the npm registry's base64-encoded SRI format (sha512-<base64>) without accounting for the encoding difference. They represent the exact same digest, just serialized differently. The value in package.json was correctly generated by corepack use pnpm@11.1.2 and will validate correctly.

I'll resolve my comment and record this for future reviews.

(╯°□°)╯ 🐇 hops away in embarrassment


🏁 Script executed:

#!/bin/bash
# Resolve my own comment on the PR
gh api graphql -f query='
{
  repository(owner: "contedra", name: "toolkit") {
    pullRequest(number: 40) {
      reviewThreads(first: 50) {
        nodes {
          id
          isResolved
          comments(first: 1) {
            nodes {
              author { login }
              body
              url
            }
          }
        }
      }
    }
  }
}'

Length of output: 76


I wasn't able to resolve the comment programmatically due to a missing auth token in the sandbox. You can resolve it manually by clicking Resolve conversation on the thread. Sorry again for the noise!


✏️ Learnings added
Learnt from: ms2sato
Repo: contedra/toolkit PR: 40
File: package.json:11-11
Timestamp: 2026-05-16T05:56:43.394Z
Learning: In `package.json`, the `packageManager` field uses corepack's hash format where the SHA-512 digest is **hex-encoded** (e.g., `pnpm11.1.2+sha512.<hex>`). The npm registry's `dist.integrity` field encodes the **same** SHA-512 digest as **base64 SRI** (`sha512-<base64>`). Do not flag these as mismatched hashes — they are identical digests in different encodings. The correct corepack hash can be obtained by running `corepack use pnpm@<version>`.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment thread README.md Outdated
pnpm 11 escalates ERR_PNPM_IGNORED_BUILDS to a fatal error (exit 1),
which broke CI on the pnpm 10->11 upgrade. List the affected build
scripts in allowBuilds with `false` — keeping the pnpm 10 behaviour
(scripts not run, pipeline already green) while still failing CI if a
new dependency introduces an unreviewed build script.

Also fix the per-command bypass example: pnpm CLI config overrides use
kebab-case, so --config.minimum-release-age=0 (was camelCase).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ms2sato ms2sato merged commit fc29f31 into main May 17, 2026
3 checks passed
@ms2sato ms2sato deleted the chore/setup-package-age-gate branch May 17, 2026 07:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant