SafeInstall
safeinstall-cli · 0.1.0

Stop risky package installs before they run.

SafeInstall wraps npm, pnpm, and bun: install policy runs first, then the real tool. Open source, MIT licensed. No account required.

Global install

$npm install -g safeinstall-cli

One-off / CI

$npx safeinstall-cli check

Node >=20 · Open source · MIT license

allowed — stderr before pnpm runs
$safeinstall pnpm add axios
Using config: built-in defaults
Allowed: policy checks passed.
# then pnpm output follows on stdout
blocked — policy output (exit 2)
$safeinstall pnpm add compromised-pkg@9.9.9
Using config: built-in defaults
Install blocked.
- compromised-pkg@9.9.9
Blocked: release too new (…; minimum is 72 hours).
Suggestion: Retry later or lower minimumReleaseAgeHours …
Blocked: install script present (… has postinstall).
Suggestion: Allow this package explicitly in allowedScripts …
Why this exists

Package install is now an attack surface.

Supply-chain attacks through npm and similar registries are increasing. The way developers install packages has changed. The tooling has not kept up.

01

Package installs are an attack surface.

Lifecycle scripts run arbitrary code at install time. A single malicious dependency can exfiltrate tokens, modify files, or establish persistence — before your app even starts.

02

AI coding makes this worse.

When an AI assistant suggests a package, most developers install it immediately. There is no pause for research, no audit, no second opinion. The speed that makes AI coding powerful also removes the friction that used to catch bad packages.

03

Scanners alert after the fact.

npm audit and most security tools tell you about known vulnerabilities in packages you already installed. They do nothing about install-time script execution. They do not prevent the package from running during install.

04

The fix is not more dashboards.

Developers need a guardrail that blocks many risky installs before they run—policy first, then the package manager. Not only a report after the fact.

What it blocks

Four protections. On by default.

SafeInstall evaluates policy before your package manager runs. Optional safeinstall.config.json tightens or relaxes rules per project.

Blocked: release too new

Fresh registry releases

By default, registry versions newer than 72 hours are blocked (configurable via minimumReleaseAgeHours). That window is where many supply-chain publishes get noticed late.

Blocked: install script present

Lifecycle scripts

Packages with preinstall, install, or postinstall scripts are blocked unless you allow those scripts per package in allowedScripts. SafeInstall still forwards --ignore-scripts to the package manager by default so installs stay non-blind.

Blocked: untrusted source

Non-registry sources

Git, tarball, and direct URL installs are blocked unless that source type is in allowedSources. Registry, workspace, file, and directory sources are allowed by default.

Blocked: trust level dropped

Trust downgrades

Two cases: a registry dependency moves to git/url/tarball, or a new registry version introduces lifecycle scripts where the installed version had none (compared using local node_modules when present).

How it works

Evaluate first. Execute second.

No registry proxy. No middleware on downloads. Policy runs locally, then the underlying tool runs as usual.

1

You run SafeInstall

Prefix your package manager command with safeinstall.

$safeinstall pnpm install
2

SafeInstall evaluates

For registry packages it uses public npm registry metadata (publish time, scripts). Project installs for pnpm/npm use the lockfile so versions match what the repo will install.

3

Block or allow

Policy violations exit with code 2 and print Blocked: … lines. Clean runs print Allowed: policy checks passed. then invoke the manager.

4

Package manager runs

On allow, your exact command runs. SafeInstall appends defaults like --ignore-scripts per packageManagerDefaults unless you change them.

stderr — allow
$safeinstall pnpm add zod
Using config: built-in defaults
Allowed: policy checks passed.
stderr — untrusted source
$safeinstall npm install git+https://github.com/foo/bar
Install blocked.
- git+https://github.com/foo/bar
Blocked: untrusted source (git).
vs. scanners

Scanners report. SafeInstall runs first.

npm audit and similar tools report on known issues in dependencies you already installed. SafeInstall evaluates policy before the package manager: it can refuse installs that violate age, script, or source rules, and it forwards --ignore-scripts by default unless you change defaults — see docs for behavior.

Scanners (npm audit, Snyk…)SafeInstall
When it runsAfter installBefore install
What it checksKnown CVEs in installed packagesInstall policy: age, scripts, source
OutputVulnerability reportAllow or block, with Blocked: … lines
Lifecycle scriptsDoes not block installBlocks if unallowed; default forwards --ignore-scripts to PM
Fresh release windowNoYes (default 72h minimum age)
Registry metadataVariesUses npm registry API when evaluating registry packages
Requires security expertiseTo act on results: yesReadable block reasons

Use both. They solve different problems. SafeInstall is pre-install; scanners are post-install.

Built for AI coding

Vibe coding is fast.
Blind installs are the cost.
SafeInstall is the gate.

AI assistants suggest packages in seconds. They don't check publish dates. They don't read install scripts. They don't verify the source. You type “yes” and move on.

SafeInstall adds one layer between suggestion and execution: policy. Release age, lifecycle scripts, source type, trust signals — checked before the package manager runs. You keep the speed. You lose the blind spot.

If you vibe code, this is the safety net your workflow is missing.

Works with every AI tool that suggests or runs installs

CursorGitHub CopilotClineClaude CodeWindsurfAiderDevinContinue

Typical vibe coding workflow

You"add a PDF generation library"
AIpnpm add pdf-maker@0.1.2 — "try this"
Beforepnpm add pdf-maker@0.1.2
Nowsafeinstall pnpm add pdf-maker@0.1.2
CLI examples

Same commands — SafeInstall in front.

Also supported: safeinstall init, safeinstall --json …, and project installs that resolve direct deps from lockfiles (pnpm / npm).

pnpm add — allowed
$safeinstall pnpm add axios
Using config: built-in defaults
Allowed: policy checks passed.
Release too new (hours threshold)
$safeinstall npm install react@latest
Install blocked.
- react@…
Blocked: release too new (…; minimum is 72 hours).
Suggestion: Retry later or lower minimumReleaseAgeHours…
Git / URL source blocked
$safeinstall bun add github:owner/repo
Install blocked.
- …
Blocked: untrusted source (git).
safeinstall check — direct deps
$safeinstall check
Using config: ./safeinstall.config.json
Check passed: no direct dependency policy violations found.
Who it is for

Built for developers who ship fast.

A CLI guardrail, not a platform. Scope is intentional: pre-install policy only.

Solo developers

Your machine, your responsibility.

  • AI-assisted workflows mean more installs and less package review
  • No security team to catch risky publishes for you
  • One global install — policy runs locally, no account needed
  • Use safeinstall check on direct dependencies before you ship
Startup engineering teams

Move fast. Don't run installs blind.

  • Small teams ship quickly; one bad install can hit everyone
  • Commit safeinstall.config.json so policy matches across machines
  • Exit code 2 on block is CI-friendly when you wrap installs in pipelines
  • pnpm and npm project installs honor lockfiles — fewer surprise versions
AI-first teams

Your AI writes the install command. You control the gate.

  • Using Cursor, Copilot, Cline, Claude Code, or Windsurf
  • AI suggestions skip the usual review instincts — SafeInstall does not
  • Same prefix (safeinstall) for npm, pnpm, and bun
  • JSON mode (--json) fits automation around agents and scripts
Get started

Free forever. Open source. Install in 10 seconds.

Install the CLI globally or try it with npx. No account, no sign-up, no registry auth. Read the docs · View source

$npm install -g safeinstall-cli
$npx safeinstall-cli check

Node >=20 · MIT license