The risk of a dependency does not start when you import it into a component. It starts earlier, when you decide to run pnpm add or npm install on your machine and everyone else’s.
A library can save hours. It can also bring in hundreds of transitive packages, a script that runs during installation or a version published twenty minutes ago. That is not a reason to stop using dependencies. It is a reason to stop treating them as a line of configuration with no consequences.
This has mattered more during 2026 because of several compromised packages published to npm. There is not one npm CLI vulnerability that pnpm automatically solves. The more persistent problem is supply chain risk. A legitimate package can publish a compromised version, and the package manager is the point where that code enters your environment.
That is why I use pnpm on this portfolio. Not because it protects me from everything, but because it lets me put a few reasonable barriers in place by default on a personal project that is still growing.
A dependency is more than the package you searched for
When you install a direct dependency, you also accept its dependency tree, the people or organisation publishing its versions and the way the package manager resolves them. Sometimes the real cost is not package size. It is what happens during installation or when you update months later.
Several different risks sit behind the word “dependency”.
- A package can be abandoned and stop receiving fixes.
- A name similar to a familiar library can lead to a different package.
- An update can contain changes you did not expect.
- A transitive package can add install scripts, a remote URL or a Git dependency.
- A maintainer or publishing account can be compromised.
A lockfile helps a team install the same versions. It does not decide that those versions are good. It freezes a decision you have already made. That distinction matters when an alert appears or someone proposes updating everything without reading the diff.
npm’s recent change is an improvement, not the end of the problem
Since npm 12, released in July 2026, dependency lifecycle scripts no longer run by default. Git dependencies and remote URLs also require explicit permission. That is an important change because preinstall, install and postinstall scripts have often been a route to running code during installation.
It is good news. It also avoids an easy conclusion. Approving a script does not make the package trustworthy, and disabling scripts does not replace reviewing what is being installed. The manager reduces one kind of exposure. Judgement about the dependency is still yours.
That is where the comparison with pnpm should begin, not with “npm is unsafe”. npm has strengthened its defaults. Since version 10, pnpm has not automatically run dependency postinstall scripts and it adds a few policies that I find useful right now for delaying and constraining what reaches a project.
Why pnpm fits me better right now
The main reason is not faster installs or lower disk usage. It is that pnpm lets me turn several security decisions into configuration versioned alongside the project.
Builds do not run by momentum
This repository has a pnpm-workspace.yaml file with an explicit list of dependencies I allow to build during installation.
allowBuilds:
'@parcel/watcher': true
esbuild: true
sharp: trueThat does not mean those three dependencies are infallible. It means I do not want a new dependency to run a build merely because somebody added it to the tree. If another one arrives with postinstall, pnpm requires that decision to be explicit.
That is useful when the issue is not only a malicious package created yesterday. A compromised version of a dependency that did not previously need to run anything at installation time matters too.
A newly published version can wait
pnpm 11 has a one-day minimum release age by default. During installs and updates, it avoids resolving versions that have just been published. The delay does not detect malware. It buys time for a compromised package to be discovered, removed or flagged before it enters a project.
This portfolio has exceptions for specific Astro packages already chosen in the current update. I do not see them as a list to copy. Every exception reduces protection and deserves a clear reason, especially for a new or less familiar dependency.
For an application that does not need the latest version on release day, delaying updates feels more sensible to me than installing everything new by reflex. For an important security patch, the judgement changes. That is when I need to review the advisory, affected versions and the cost of waiting.
It can also close less usual sources
pnpm can block transitive dependencies coming from Git or a tarball URL with blockExoticSubdeps. It also supports trust policies and can pin packages to a particular registry in the lockfile when a project works with more than one registry.
I would not turn on an option merely to stack security. I would first check whether it breaks a legitimate dependency and document why that exception exists. What matters to me is having these decisions visible in the repository rather than hidden in one person’s local configuration.
pnpm is not outside the reach of vulnerabilities
Using pnpm does not let you stop updating pnpm.
In May 2026, a path traversal vulnerability in pnpm could replace project paths through a transitive dependency, even with --ignore-scripts. It affected versions below 10.34.0 and the version 11 line below 11.4.0. This project pins pnpm@11.19.0, outside those ranges, but the lesson is not that pnpm won. The package manager itself is part of the supply chain.
That is why I would not treat --ignore-scripts as an absolute safe mode. It is a useful layer. It does not guarantee that a package manager bug, a weak registry configuration or a malicious dependency cannot create another problem.
Package manager versions and safeguards change. If you return to this article in a few months, check official advisories before copying any configuration. As of August 2026, npm 12 has hardened installs, while pnpm additionally offers a minimum release age, explicit build controls and provenance policies. That is the practical comparison, not a tools war.
What I look at before adding something
I do not have a formula that turns a package into a safe one. I do try to interrupt the automatic gesture of searching for a function, opening the first result and adding it.
First I ask whether it is actually needed. A utility that fits in a few lines and belongs to the project domain can be easier to review and maintain than a whole library. For complex work such as a parser, a date engine or a protocol integration, writing my own solution out of pride often increases risk instead.
Then I look at more concrete questions.
- What problem does it solve, and does the project already solve it another way?
- Who maintains it, when was a stable version released and how are changes documented?
- How many dependencies does it add, and does it need install scripts?
- Which exact version ends up in
pnpm-lock.yaml? - What changes on update, instead of accepting a bulk update without reading it?
If a package is new to me or its installation behaviour concerns me, I prefer to inspect its tarball or published files before bringing it into the project. I do not need to audit every line of every dependency to work with JavaScript. I need to recognise when a small decision is widening the trust boundary too far.
The lockfile and installation environment matter
Committing pnpm-lock.yaml is essential for repeatable installs, but it also needs to be used properly. In CI, a frozen install stops a range such as ^7.0.0 from silently becoming a new version during a deployment.
That does not prevent a fixed version from having a known vulnerability. For that, you need alerts, regular reviews and intentional updates. It also does not protect secrets available to an install script. On a machine or CI environment with publishing tokens, cloud credentials and SSH keys, installing dependencies deserves more care than it does in an isolated environment.
If I ever published packages from automation, I would prefer npm trusted publishing with OIDC over a permanent write token. Not because it removes every risk, but because it avoids leaving a reusable credential in CI secrets.
The decision I want to be able to explain
I do not want my response to an alert to be switching package managers and calling the problem solved. I want to be able to explain why a dependency is in the project, which version was installed, what was allowed during installation and what I would do if an advisory appeared tomorrow.
pnpm fits this portfolio better right now because it makes three decisions visible that I value. Which packages may build, how long I wait before resolving a new version and which exact versions will be installed. It does not replace maintenance, review or updates. It makes them harder to forget.
This continues web security explained for developers and my review before launching a website. Website security does not start at deployment. It starts much earlier, when you choose which outside code enters the repository.