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 (one command)
macOS and Linux:
curl -fsSL https://chain305.com/install.sh | sh
Windows (PowerShell):
iwr -useb https://chain305.com/install.ps1 | iex
That one command installs the CLI (it detects your OS and arch and verifies the
SHA-256 checksum) and turns the install guard on: it adds one line to your
shell config (your PowerShell profile on Windows), so in every new terminal
npm, pip, go, cargo and gem installs are checked before they download.
The installer ends with a Guard: line that says whether the guard is on.
- To install the binary only, set
CHAINSAW_NO_GUARD=1on the shell that runs the script:curl -fsSL https://chain305.com/install.sh | CHAINSAW_NO_GUARD=1 sh. - In CI (
CIset) the installer skips the guard automatically; see Unattended install in CI. - Windows: if your PowerShell execution policy is
Restricted(the default on many PCs), profiles don’t load. The installer says so instead of claiming the guard is on. Allow it for your user withSet-ExecutionPolicy -Scope CurrentUser RemoteSigned.
Or build from source with the Go toolchain. This installs the binary only, so turn the guard on yourself afterwards:
go install github.com/chain305/chainsaw-core/cmd/chainsaw@latest
chainsaw guard init --install
Open a new terminal, then check it’s wired up:
chainsaw doctor
chainsaw guard status
Step 2: Guard an install
With the guard on, use your normal command: npm install lodahs is refused on
its own. You can also put chainsaw in front of a command explicitly, which
works even where the guard isn’t loaded (a script, or cmd.exe). 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: It’s already automatic
The installer turned the guard on in Step 1, so npm, pip, go, cargo and
gem route through it in every new terminal. It added this one line to your
shell config, which you can read and remove at any time:
# ~/.zshrc or ~/.bashrc (added by the installer)
eval "$(chainsaw guard init zsh)"
# ~/.config/fish/config.fish
chainsaw guard init fish | source
If the Guard: line said it was skipped, or you installed with go install,
add it yourself with chainsaw guard init --install (it’s idempotent; preview
first with --dry-run). For the current shell only, run the eval line above.
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.