How to Secure npm, PyPI and Maven Dependencies With a Vetted Pull-Through Cache

Key takeaways
- The registry is the only chokepoint that changes every build at once, without editing manifests, lockfiles or CI configuration.
- Recent compromises were live for minutes to hours, so the control has to be automated — a per-repository process cannot react in time.
- A cooldown of 24 to 72 hours is the highest-value single policy, because most malicious versions are removed inside that window.
- Sequence the rollout: inventory, stand up, repoint, report-only, enforce. Enforcing before the easy path exists causes outages and kills adoption.
- Vetting is not remediation. A cache controls what enters; it does not patch what is already in your tree.
A vetted pull-through cache sits between your developers and the public package registries, fetches each requested version once, applies a policy before releasing it, and serves it locally thereafter. It is the only control in this category that changes what your builds consume without changing a single line in a manifest, lockfile or CI script. That property is why it has become the default rollout pattern for teams trying to reduce dependency risk across more repositories than they can reasonably edit.
This guide covers what to put in front of the cache, how to sequence the rollout, and what the approach does not fix.
Why registry-level control beats per-repository fixes
The arithmetic is unforgiving. A policy enforced in a repository has to be adopted by every repository, which means negotiating with every team that owns one. A policy enforced in the registry applies the moment the next build runs.
The attack data explains the urgency. Unit 42's tracking of the npm supply chain shows how little time a per-repository process has to react:
- 11 May 2026 — 84 malicious artifacts across 42 @tanstack/* packages published within six minutes; by end of day, 373 malicious versions across 169 npm packages were documented (Unit 42).
- 19 May 2026 — 639 malicious versions across 323 @antv packages in about one hour (Unit 42).
- 22 April 2026 — a malicious @bitwarden/cli version was publicly available for roughly 1.5 hours (Unit 42).
An incident measured in minutes cannot be met by a process measured in sprints. Whatever decides which versions are installable has to be a system, and it has to sit at the chokepoint.
What a "vetted" cache adds to an ordinary one
A plain pull-through cache is a performance and availability feature: fetch once, serve many, survive an upstream outage. Vetting turns the same chokepoint into a policy decision point. The controls worth running there, in rough order of value per unit of disruption:
- A cooldown window. Refuse versions published in the last 24 to 72 hours. Unit 42 recommends this range specifically because most malicious packages are removed inside it.
- Install-script suppression. Set ignore-scripts=true in .npmrc. Install-time hooks are the execution path in the majority of recent npm compromises.
- Lockfile-faithful installs. npm ci rather than npm install, so a build never silently resolves a new version.
- Version-inflation detection. Attackers publish above the latest legitimate release so permissive ranges such as ^2.x pull the bad version; a policy that flags an unexpected jump catches that class.
Two more controls belong nearby rather than in the cache itself: provenance verification on what the cache serves, and egress filtering in CI so a payload that does execute cannot reach its collection endpoint.
The rollout sequence that does not cause an outage
Order matters more than tooling here. The failure mode is enforcing before the easy path exists, which converts a migration into an incident and spends the goodwill the programme depends on.
- Inventory what is actually pulled. The real list of distinct packages is almost always far shorter than the repository count suggests, and it makes the rest of the work finite.
- Stand the cache up against existing upstream sources, with no policy. Nothing changes behaviourally. This proves the plumbing — credentials, TLS, storage — while the blast radius is zero.
- Point developers and CI at it. Registry configuration only; no manifest edits. Measure cache hit rate until it stabilises.
- Turn on policy in report-only mode. You now know exactly what a cooldown or a script-suppression rule would have blocked last month, which is the number that wins the argument internally.
- Enforce, one ecosystem at a time. npm first if that is where your exposure is; Maven and NuGet usually last, because their release cadences are slower and the cooldown bites less.
Each registry implements this differently — Artifactory remote repositories, Nexus proxy repositories, ECR pull-through cache rules, Harbor and Quay equivalents — but the sequence is the same regardless of product.
What this does not fix
A cache changes the default source. It is not a boundary, and treating it as one produces a false sense of coverage.
- Developers can still reach upstream directly unless network policy stops them. The cache is a default, not a wall.
- A cooldown does not stop a slow compromise. A malicious version that survives undetected past the window arrives on schedule.
- It does nothing about packages you already trust. A maintainer account compromised in a package you installed two years ago is a different problem.
- It does not reduce your CVE count. Vetting controls what enters; it does not patch what is already there.
That last point is the one most often conflated. Supply-chain vetting and vulnerability remediation are separate programmes with separate owners, and a cache advances only the first. Our write-up on preventing supply chain attacks in open source dependencies covers the vetting side in more depth, and OSS vulnerability scanning covers the remediation side.
Where hardened libraries fit
Once the cache is the chokepoint, the source it points at becomes a choice rather than a given. Repointing it at a vetted or patched build of the same package changes what every subsequent build consumes, with no further developer action — the same mechanism that made adoption cheap makes substitution cheap.
The questions to ask a provider of patched packages are unglamorous and decisive: which ecosystems are covered, how long a given version keeps receiving fixes, whether a machine-readable statement accompanies each fix so your scanner does not re-report it, and whether the artifacts remain standard packages you could walk away from.
Echo states that critical and high CVEs are triaged within 24 hours and fixed in up to seven days, and that images and packages ship signed and attested with SBOM, provenance and VEX (echo.ai/product). For the developer-workflow side of the same problem, "How to use npm packages without risking your pipeline" (echo.ai/blog/npm-packages-pipeline) covers what changes inside a repository rather than at the registry.
FAQs
Does a pull-through cache slow down builds?
In steady state it speeds them up, because a cache hit is served from your own infrastructure rather than the public internet. The first pull of any uncached version is marginally slower while the cache populates. The real cost is cold-start behaviour: during a large parallel deployment against an empty cache, you briefly get no-cache performance, including exposure to upstream rate limits.
What cooldown window should we set?
Unit 42 recommends blocking versions published in the last 24 to 72 hours, on the basis that most malicious packages are removed inside that window. Start at 24 hours, which almost no team notices, and extend if your release cadence tolerates it. Keep a documented break-glass path for a genuine emergency patch, because the one time you need a fresh version urgently will be a security fix.
Will this break teams that need the newest package immediately?
Rarely, and the exceptions are predictable. Most dependency updates are not time-critical, and the teams that genuinely need same-day versions usually know who they are. Handle them with a scoped exemption rather than by weakening the global window. Running the policy in report-only mode first tells you exactly how many builds would have been affected, which converts the argument from speculation to data.
Does this replace software composition analysis?
No. The two answer different questions. Composition analysis tells you what is in your dependency tree and which known vulnerabilities apply to it. A vetted cache decides what is allowed to enter that tree in the first place. One is detection, the other is prevention, and a mature programme runs both — the cache reduces the inflow that analysis then has to triage.
How does this work in an air-gapped environment?
It does not, in this form. A cache assumes it can reach upstream when it misses, which a disconnected network cannot do. The equivalent pattern is a seeded internal mirror populated through a controlled transfer process, with the same vetting policy applied at the point of transfer rather than at the point of request. The rollout sequence is unchanged; only the population mechanism differs.
Frontier models can now find and exploit zero days in your code
Find out what to do when there's no CVE, scanner alert or fix available yet.
What are the 7 blind spots in your vulnerability scans?
Discover when "0 vulnerabilities" doesn't actually mean you're clean.
.png)




.avif)
.avif)