Safeguard
Open Source Security

What to check before installing an open source package

A practical guide to vetting open source packages before you install them — real incidents, concrete checks, and how reachability analysis cuts through CVE noise.

James
Principal Security Architect
7 min read

In September 2025, an attacker phished the maintainer of the widely-used chalk and debug npm packages, pushed malicious versions that tried to drain cryptocurrency wallets, and briefly touched an install base measured in billions of weekly downloads before the packages were pulled. Six months earlier, a backdoor was found inside xz-utils (CVE-2024-3094) after more than two years of patient social engineering by a fake co-maintainer — caught only because a Microsoft engineer noticed SSH logins running about 500 milliseconds slower than usual. Open source now makes up an estimated 70-90% of the code in most applications, and a single npm install or pip install pulls in a full tree of transitive dependencies you never explicitly chose or reviewed. Vetting a package before you add it isn't optional due diligence anymore — it's the difference between shipping your code and shipping an attacker's supply chain. Here's what to actually check, with specifics, before you run the install command.

Who actually maintains this package, and can you trust them?

Check the maintainer count, account age, and how recently they've been active — a package with a single maintainer who hasn't logged a commit in 18+ months is the exact profile attackers look for when they offer to "help out." That's precisely how the event-stream incident unfolded in November 2018: the original maintainer, burned out and unpaid, handed publish rights to a stranger who added a malicious dependency called flatmap-stream designed to steal Bitcoin from the Copay wallet app. The xz-utils backdoor followed the same playbook at a much larger scale — "Jia Tan" spent over two years submitting legitimate patches and building trust before landing the malicious commit in liblzma in early 2024. Before you install, look at the GitHub contributor graph, whether the project is backed by an organization or foundation, and whether it passes the OpenSSF Scorecard "Maintained" check rather than just a "recently updated" badge.

Has this package's publishing account ever been compromised?

Yes is a live possibility, not a hypothetical — Sonatype identified over 245,000 malicious open source packages in 2023 alone, nearly triple what it found in all of 2022, and the trend accelerated further in 2025 with a self-propagating npm worm known as Shai-Hulud. That worm, discovered in September 2025, used stolen credentials to automatically republish itself into victims' own GitHub repositories, spreading without any human attacker driving each step. It followed a string of account-takeover incidents: ua-parser-js (versions 0.7.29, 0.8.0, and 1.0.0) was compromised in October 2021 to install cryptomining and credential-stealing malware on any machine that ran npm install, and node-ipc shipped so-called "protestware" in March 2022 that wiped disks on machines with Russian or Belarusian IP addresses. Before installing, check the package's registry page for open security advisories, look for version jumps that have no matching commit or tag in the source repository (a classic sign of a registry-only publish), and run npm audit or pip-audit against your lockfile, not just against the top-level dependency list.

Does a known CVE in this package actually affect your application?

Usually not directly — most applications never execute the specific function a CVE is reported against, because the vulnerable code path sits behind a feature the application doesn't use. Reachability analysis answers this by tracing your actual call graph down into a dependency's internals rather than just matching version strings against a vulnerability database. Teams that adopt call-graph-based reachability commonly find that a large majority of the CVEs a traditional SCA scanner flags as "critical" are never invoked at runtime in their specific build, because the vulnerable function lives behind conditional logic, an unused module, or a code path gated by a feature flag. That distinction matters operationally: a security team chasing every CVE with equal urgency will burn engineering time on issues that pose zero real exploitability, while an actually-reachable vulnerability in a rarely-scanned dependency sits unpatched. Before you accept a "critical" severity rating at face value, check whether the CVE's proof-of-concept requires calling a specific function, and whether that function shows up anywhere in your own code's call stack.

Can you verify where this package actually came from before you install it?

Yes, but only if the publisher attached verifiable provenance, and most packages still don't. npm introduced provenance attestations in 2023 that cryptographically tie a published package to the exact CI build and source commit that produced it via Sigstore, and Python's PyPI added a comparable attestation format (PEP 740) — check for that badge on the registry page rather than assuming a tarball matches its listed GitHub source. The cost of skipping this check showed up clearly in June 2024, when the domain behind the popular polyfill.io CDN script was sold to a new owner and started injecting malware into every site that still referenced it, affecting an estimated 100,000+ websites before Cloudflare, Fastly, and Google began actively blocking or rewriting the domain. That incident involved a hosted script rather than a registry package, but the lesson transfers directly: trusting a source forever, without re-verifying it, is how a clean dependency turns into a live backdoor months or years after you first added it. Pin to a specific commit hash or signed release, not a mutable tag or a remote URL you don't control.

What else is this package pulling in behind your back?

Almost certainly more than the one line you added to your manifest — industry research on npm dependency graphs has repeatedly found that a typical project's direct dependency count (often well under 100 packages) balloons into several hundred once transitive dependencies are counted. Each of those transitive packages is a maintainer you didn't vet, a publishing account that could be phished, and a CVE that could land in your build without ever showing up in your top-level package.json or requirements.txt. This is exactly the gap a Software Bill of Materials is built to close: generating an SBOM (in CycloneDX or SPDX format) at build time gives you a complete, machine-readable inventory of every package — direct and transitive — that actually ships in your artifact, not just the ones you remembered to check. Before merging a new dependency, regenerate your SBOM and diff it against the previous version to see exactly what new packages, maintainers, and licenses just entered your supply chain.

How Safeguard Helps

Safeguard turns this checklist from a manual, one-time review into a continuous, automated control. Our reachability analysis traces real call graphs from your application code into every dependency so your team sees which CVEs are actually exploitable in your build, cutting through the noise of severity scores that ignore whether the vulnerable function is ever called. Griffin AI, Safeguard's security analyst agent, correlates maintainer risk, package provenance, and behavioral signals — flagging the maintainer-takeover and account-compromise patterns behind incidents like event-stream and ua-parser-js before a malicious version ever reaches your build. Safeguard generates and ingests SBOMs automatically on every build so you always have a current, auditable inventory of direct and transitive dependencies, and when a fix is available, Safeguard opens an auto-fix pull request with the minimal version bump needed — so vetting a package doesn't end at install time, it stays current for as long as that package stays in your codebase.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.