Open source is fantastic, and it is also your biggest attack surface. A typical application is built mostly from libraries other people wrote, pulled in automatically through a chain of dependencies you never explicitly chose. Securing that supply chain is not about avoiding open source; it is about adopting a handful of habits that make it much harder for a bad or vulnerable package to hurt you. This guide walks beginners through those habits, in order, with commands you can run today.
What you will accomplish
You will lock down how dependencies enter your project, learn to vet a new package before installing it, and set up a repeatable way to catch vulnerable ones. These practices together prevent the most common supply-chain incidents.
Prerequisites
- A project with a package manager such as npm, pip, or Maven.
- A terminal and basic command-line comfort.
- Git for committing your lockfile.
- The Safeguard CLI, installed in Step 5.
Step 1: Commit your lockfile
A lockfile records the exact version of every package, direct and transitive, that your project resolved. Committing it means everyone, including your CI, installs precisely the same code. Make sure it is tracked:
git add package-lock.json
git commit -m "chore: commit lockfile"
Without a lockfile, a fresh install can silently pull newer, unreviewed versions.
Step 2: Install from the lockfile, not around it
In automated environments, use the install command that respects the lockfile exactly and fails if the manifest and lockfile disagree:
npm ci
Unlike a plain install, npm ci will not quietly change versions. That predictability is a security property.
Step 3: Vet a package before you add it
Before adding a new dependency, spend two minutes checking it. Look at how widely it is used, when it was last updated, and how many other packages it drags in:
npm view express versions --json | tail
npm view express maintainers
Red flags for a beginner: a package with almost no downloads, a name suspiciously close to a popular one, a very recent first release, or a single new maintainer on a formerly popular package. Typosquatting and account takeovers are real, so a moment of skepticism pays off.
Step 4: Prefer fewer, well-maintained dependencies
Every dependency is trust you extend to a stranger, and every transitive dependency multiplies it. Before adding a library for a small task, ask whether a few lines of your own code would do. Fewer dependencies means a smaller attack surface and less to keep updated.
Step 5: Scan continuously for known vulnerabilities
Vetting stops bad packages from entering; scanning catches good packages that later turn out to be vulnerable. Install the CLI and scan:
curl -sSfL https://get.safeguard.sh/install.sh | sh
sg scan --fail-on high
Run this on every change and on a schedule. A package that was clean when you added it can have a critical vulnerability disclosed months later with no action on your part.
Step 6: Keep dependencies current, deliberately
Old dependencies accumulate vulnerabilities. Update on a regular cadence, one careful change at a time, and verify with your tests after each:
npm outdated
npm install express@latest
npm test
Small, frequent updates are far safer than a giant once-a-year upgrade that touches everything at once.
How to know it worked
- Your lockfile is committed and
npm ciinstalls cleanly from it. - You can name at least two red flags you would check before adding a new package.
sg scan --fail-on highruns on your changes and exits cleanly when no serious findings exist.- Your dependencies are not years out of date.
If entry is controlled by a committed lockfile and known vulnerabilities are caught by a recurring scan, your open-source supply chain is in solid shape.
Next steps
- Automate the scan in CI so a vulnerable dependency blocks a merge instead of reaching production.
- Watch for typosquatting and dependency confusion, two common tricks for slipping malicious packages in; the concepts library explains both.
- Track licenses, since open-source licenses carry obligations, not just security risk.
- Adopt automated fixes so staying current is low-effort.
To understand how a scanner tells an exploitable dependency from a harmless one, read about software composition analysis. The Safeguard CLI runs the same checks locally and in your pipeline, so nothing slips through the gap between them. As your dependency count grows, compare what each plan covers on the pricing page, and build your fundamentals in the Safeguard Academy.
Frequently Asked Questions
Why is a lockfile a security feature? A lockfile pins the exact version of every direct and transitive dependency, so every install reproduces the same code you reviewed and tested. Without it, a fresh install can pull newer, unvetted versions, which means the code running in production may differ from what you actually approved.
How do I check whether a package is trustworthy before installing it? Look at its download volume, how recently and regularly it is maintained, its maintainer history, and how many transitive dependencies it introduces. Be wary of names that closely resemble popular packages, brand-new packages with no track record, and sudden maintainer changes on established ones, since these are common signs of typosquatting or takeover.
Is it bad to have a lot of dependencies? Not inherently, but every dependency expands your attack surface and your maintenance burden. For small tasks, a few lines of your own code can be safer than pulling in a library and its entire transitive tree. The goal is to be deliberate, not to add dependencies reflexively.
Do I still need to scan if I vetted everything at install time? Yes. Vetting only reflects what was known when you added the package. Vulnerabilities are disclosed against existing libraries every day, so a package that was clean at install can become a critical finding later. Continuous scanning is what catches that shift.
Want continuous scanning and automated fixes for your dependencies? Sign up at app.safeguard.sh/register, and keep learning in the Safeguard Academy.