How to Block Malicious and Typosquatted Packages at Install Time with the Chainsaw CLI
Run npm, pip, or go through the free Chainsaw CLI so malicious and typosquatted packages are refused before they enter your build — entirely on your machine, no server, nothing leaves the box.
Overview
The Chainsaw CLI can wrap your package manager and act as an install-path
firewall: run chainsaw npm install … (or pip, or go) and Chainsaw
evaluates each package before it enters your build, refuses anything
malicious or typosquatted, then hands off to the real tool. The evaluation runs
entirely on your machine — no server, no infrastructure — so you can adopt it on
a laptop or a CI job. (Anonymous usage telemetry is off until you opt in; see
Telemetry and privacy.)
This is the free, open-source CLI (github.com/chain305/chainsaw-core).
No account required — not to block packages, and not for the feed either:
chainsaw guard update (Step 7) pulls the full public OpenSSF
malicious-packages feed directly from OpenSSF without sign-in. Guard blocks are
recorded on this machine, and chainsaw guard status is always the local
record. Signing in changes nothing about the feed — with telemetry on, blocks
from this machine are also recorded against your org and appear on the
dashboard alongside proxy and CI activity. With telemetry off, they stay here.
Prerequisites
- The
chainsawCLI on yourPATH(see Step 1). - npm, pip, or the Go toolchain installed (Chainsaw delegates to whichever you use).
Step 1: Install the CLI
Pre-built binary (detects your OS/arch, verifies the SHA-256 checksum):
curl -fsSL https://chain305.com/install.sh | sh
Or from source with the Go toolchain:
go install github.com/chain305/chainsaw-core/cmd/chainsaw@latest
Verify it’s wired up:
chainsaw doctor
Step 2: Guard an install
Put chainsaw in front of your normal command. A clean package installs as
usual; a typosquat is refused before anything is fetched into your project.
# Clean — Chainsaw checks it, then runs the real `npm install lodash`.
chainsaw npm install lodash
# Typosquat — refused; the real npm is never invoked.
chainsaw npm install lodahs
chainsaw: BLOCKED npm:lodahs — looks like a typosquat of "lodash" (distance 1, edit-distance)
chainsaw: refused at install path. Nothing was installed.
The wrapper exits non-zero on a block, so it also gates CI steps.
Step 3: Known-malicious packages
Chainsaw ships an offline floor of well-known supply-chain attacks. These are refused with no network access:
chainsaw npm install event-stream@3.3.6 # the 2018 flatmap-stream attack
chainsaw pip install colourama # typosquat-malware of colorama
chainsaw: BLOCKED npm:event-stream@3.3.6 — known-malicious (CHW-FLOOR-event-stream-3.3.6)
Clean versions of the same package are unaffected — the floor is version-exact,
so npm install event-stream (a current release) installs normally.
Step 4: Scan a whole lockfile
With no named package, Chainsaw scans the resolved dependency tree, so a malicious transitive dependency is caught too:
chainsaw npm ci # scans package-lock.json
chainsaw pip install -r requirements.txt # scans the requirements file
chainsaw: scanning 412 packages from lockfile
chainsaw: BLOCKED npm:ua-parser-js@0.7.29 — known-malicious (CHW-FLOOR-ua-parser-js)
chainsaw: refused at install path. Nothing was installed.
Step 5: Go modules
chainsaw go get github.com/some/module@v1.2.3
Step 6: Make it automatic (recommended)
Typing chainsaw each time is easy to forget. Add a one-liner to your shell
config and npm, pip, and go route through the guard transparently:
# ~/.zshrc or ~/.bashrc
eval "$(chainsaw guard init zsh)"
# ~/.config/fish/config.fish
chainsaw guard init fish | source
Now npm install … is checked automatically — the guard evaluates the package,
then hands off to the real npm. (It’s recursion-safe: Chainsaw resolves the
real tool via PATH, which shell functions don’t shadow.)
Step 7: Add full known-malicious coverage (optional)
The built-in floor covers the famous attacks offline. To pull the full OpenSSF malicious-packages dataset for local use, run the opt-in updater (the only command that fetches feed data, and only when you run it):
chainsaw guard update
It writes a local cache that the guard merges on top of its floor; after that,
known-malicious coverage is the full set, still evaluated on your machine.
chainsaw guard update pulls that data directly from OpenSSF — no Chainsaw
sign-in required — and the built-in floor keeps working offline either way.
Check what coverage and feed you have at any time:
chainsaw guard status
Enable shell completion (optional)
chainsaw ships tab-completion for bash, zsh, fish, and
PowerShell. Load it for the current shell:
# zsh (most macOS setups) — add to ~/.zshrc:
source <(chainsaw completion zsh)
# bash — add to ~/.bashrc:
source <(chainsaw completion bash)
# fish:
chainsaw completion fish | source
Completion covers subcommands, their flags, and the guarded package managers
(chainsaw npm, chainsaw pip, …). Run chainsaw completion --help for the
per-shell path that persists across sessions.
Telemetry and privacy
Anonymous usage telemetry is off until you opt in. The first interactive run
asks yes/no (default No); answer yes and the guard reports how it’s adopted and
where it refuses packages. If it can’t ask — non-interactive shells, CI — it
stays off and collects nothing until you run chainsaw telemetry on. Your
protection is always evaluated entirely on your machine — telemetry is a
separate, after-the-fact event. Once you’ve opted in and no server is
configured, events go to the public ingest at https://chain305.com.
Turn it on or off any time:
chainsaw telemetry on # opt in (persisted)
chainsaw telemetry off # opt back out (persisted)
Force it off regardless of consent:
export CHAINSAW_TELEMETRY_DISABLED=1 # disable all telemetry
export CHAINSAW_OFFLINE=1 # disable telemetry + make no network calls at all
export CHAINSAW_NO_NUDGE=1 # silence in-product CTAs (telemetry consent unaffected)
Full collection details — the exact events and fields — are in the Telemetry reference.
How it decides (and what it covers)
| Signal | Coverage | Network |
|---|---|---|
| Typosquat | npm, PyPI, Go | offline |
| Known-malicious floor | curated famous attacks (npm + PyPI) | offline |
| Known-malicious (full) | full OpenSSF set after chainsaw guard update | opt-in fetch, then offline |
Block policy: known-malicious and high-confidence typosquats are refused;
medium-confidence typosquats are allowed with a warning. If signal coverage is
thin, the guard fails open with a visible notice rather than blocking your
work — a tool that breaks npm install gets uninstalled.
Next Steps
- How to Set Up Chainsaw as Your Organization’s Package Proxy — move from per-developer guarding to an org-wide install-path proxy.
- How to Configure Your Package Manager to Use Chainsaw — permanent proxy configuration across ecosystems.