0003. pnpm and supply-chain policy
- Status: Accepted
- Date: 2026-10-10
- Questions: B3, F10
Context
Section titled “Context”npm supply-chain attacks usually arrive through brand-new versions and install scripts. pnpm (11+) can refuse both by policy.
Decision
Section titled “Decision”- pnpm (B3) with
nodeLinker: hoistedinpnpm-workspace.yaml. A flatnode_modulesavoids Metro, CocoaPods and Gradle autolinking resolution problems. minimumReleaseAge: 4320(3 days). New versions are not installed until they are three days old; exceptions go inminimumReleaseAgeExcludewith a reason.- Build scripts are denied by default. Only packages listed
trueunderallowBuildsmay run install scripts. Today none need to. Explicitly denied:@firebase/util,protobufjs(scripts unused by React Native),esbuildandunrs-resolver(their native binaries arrive as optional dependencies). trustPolicy: no-downgradeand the defaultblockExoticSubdeps: true. Versions older than 30 days are exempt (trustPolicyIgnoreAfter), because the check targets fresh takeovers and old releases often predate provenance. Reviewed exceptions go intrustPolicyExcludewith a reason and date (today:@expo/*, the same Expo maintainer publishing every release without provenance).- Renovate (F10), weekly, with React Native packages grouped together and automerge only for dev tooling. Renovate’s own
minimumReleaseAgematches pnpm’s. - CI installs with
--frozen-lockfile.
Consequences
Section titled “Consequences”- An urgent security fix younger than three days needs an explicit, reviewed exclude entry.
- Contributors need pnpm.
packageManagerinpackage.jsonpins the version through Corepack.
Alternatives considered
Section titled “Alternatives considered”- Yarn 4, Bun, npm: none has an equivalent built-in release-age and build-script policy.