Installing one package commonly installs hundreds. Each was chosen by the author of the one above it, updates automatically, and executes with the same privileges as your own code. What that actually exposes, why the usual advice does not scale, and the small number of measures that change the shape of the risk.
One decision, hundreds of consequences
You evaluate one package. You install a tree.
The authors of everything beneath the top level were chosen by somebody else, applying their own judgement, for their own problem, at some earlier time. None of them knows what you are building or what your process can reach.
That is not a criticism of anybody in the chain. It is a description of where the decision was actually made, which is several levels above the code now running in your environment.
Where the code actually runs
Three places, and the second is the one people underestimate.
In your build environment, which typically holds credentials — registry tokens, deploy keys, signing material — and is trusted precisely because it is internal.
At install time, before anybody has reviewed anything, where toolchains that permit install scripts execute arbitrary code as whichever account ran the install.
In production, with whatever your process can reach, because a dependency is not sandboxed from the application that imported it.
Build-time exposure is frequently worse than runtime. Build environments are permissive by design, watched less closely than production, and hold the credentials that would let somebody modify what you ship to everybody else.
Why the usual advice does not scale
Review your dependencies is correct at ten and meaningless at nine hundred.
The advice is not wrong. It is priced for a situation that no longer exists, and repeating it now mostly produces guilt, which is not a control. A team that cannot possibly do the thing being recommended will conclude either that they are failing or that the advice is noise, and neither conclusion improves anything.
The three events that actually cause harm
A maintainer account is compromised and a legitimate package publishes something new under a name you already trust.
A package changes hands — transferred, sold, inherited — to somebody with different intentions and the same publishing rights.
A name is created resembling a real one and installed by mistake.
Only the third has anything to do with your vigilance. The first two occur entirely upstream of any decision available to you, which is why a strategy built on being careful cannot address them.
What changes the shape of the risk
Engineering rather than diligence, because diligence does not scale and engineering does.
Pin exact versions, so that taking an update is an action somebody performs rather than an event that happens on a Tuesday.
Separate build credentials from anything that matters. Short-lived, narrowly scoped, and unable to reach production on their own.
Disable install-time scripts where the toolchain permits. Blunt, occasionally inconvenient, and it removes the earliest and least-observed execution point.
Vendor or mirror what you depend on, so an upstream deletion or change is something you adopt rather than something you receive.
Reduce the count, which is the only measure that improves all the others at once.
Reducing the count is the underrated one
Every dependency removed takes its own tree with it, and the tree is usually larger than the thing you wanted.
Fifty lines of your own code is frequently a better trade than a package with forty transitive dependencies — not because the package is bad, but because you are acquiring forty relationships to obtain one function.
The counterargument is real and should be stated: code you write is code you maintain, secure and get wrong yourself, without the benefit of everybody else's bug reports. That argument wins when the problem is genuinely hard — cryptography, parsing, anything with a specification and edge cases. It loses when the package is a convenience wrapper over something your standard library already does.
Popularity is evidence of usefulness. It is not evidence of safety, and the two get conflated because both feel like reassurance.
What an update actually is
Granting execution rights to code you have not read, written by people you have not met, on the grounds that the previous version was fine.
Usually the right call — most updates fix things, and refusing them all is its own vulnerability. The point is only that it is a decision being made, repeatedly, at a cadence set by other people, and that calling it maintenance obscures what is being decided.
Close
The same shape as browser extensions and connected devices: one decision, granting continuous, automatic, unreviewed change.
Wherever you find that shape, the useful question is not whether to trust the thing. It is how much you would lose if the thing changed into something else while you were not looking.
