Install time/Install hook
pnpm hooks (pnpmfile.cjs)
Automatically on every pnpm install
- Lives in
.pnpmfile.cjs in the project root- Attacker needs
- Supply-chain foothold
- Lifecycle
- InstallStartupyour codeModule loadRuntimeREPL
Runs while dependencies download and build. The app has never started.
How it runs
pnpm supports a pnpmfile.cjs (or .pnpmfile.cjs) hook file that runs during installation. It exports a hooks object with functions like readPackage that can modify any package's package.json before it's installed.
// .pnpmfile.cjs
module.exports = {
hooks: {
readPackage(pkg) {
if (pkg.name === 'lodash') {
pkg.dependencies['evil-package'] = '*';
}
return pkg;
}
}
};
This injects evil-package as a dependency of lodash during installation. The lockfile reflects the change, but the original package.json of lodash is untouched. It's dependency injection taken at its word, and it runs automatically on every pnpm install.
Defend
Review .pnpmfile.cjs in PRs; diff the lockfile for injected dependencies; forbid unreviewed hook files in CI.