SafeInstall
Package safeinstall-cli (0.1.0). Local-first wrapper: policy is evaluated before npm, pnpm, or bun runs. Blocks many risky installs by default; it is not a CVE scanner and does not prove package contents.
Overview
Prefix your package manager with safeinstall. The CLI resolves what would be installed, fetches registry metadata from the configured npm-compatible registry when needed (public npm registry by default), evaluates rules, then either exits with code 2 (blocked) or invokes the real tool—often with defaults such as ignore-scripts.
SafeInstall does not proxy the registry or modify tarballs. Network access is required to evaluate registry packages (publish time and declared scripts).
Installation
- Use Node.js >=20.
- Install globally or invoke with npx — no account or registry auth required.
Open source · MIT licensed · Source on GitHub
Usage
Pass through the same arguments you would use with the underlying tool.
Project installs
For pnpm install and npm install / npm ci, direct dependency versions come from pnpm-lock.yaml or package-lock.json (or shrinkwrap)—not loose ranges in package.json alone. Stale, missing, or mismatched lockfile entries fail closed instead of guessing.
If packageManager is set in package.json, using a different CLI is blocked. Workspace-targeting flags that may touch multiple packages (e.g. pnpm --filter, npm --workspace) are blocked; use -C or --prefix for a single package directory.
bun install still uses manifest-oriented analysis; full lockfile parity with npm/pnpm is not implemented yet.
Policy (defaults)
These are the main gates. Adjust or exempt via config where documented below.
Blocked: release too newRegistry packages must be at least 72 hours old by default (minimumReleaseAgeHours).
Blocked: install script presentpreinstall, install, and postinstall on the resolved registry version are blocked unless allowed per package via allowedScripts.
Blocked: untrusted sourceallowedSources defaults to registry, workspace, file, and directory. Git, tarball, and URL installs are outside the default set.
Blocked: trust level droppedBlocks when a dependency moves from registry to git/url/tarball, or when a new registry version adds lifecycle scripts that the version already in node_modules did not declare (comparison needs that prior install present).
Configuration
Optional safeinstall.config.json is discovered by walking upward from the effective project directory; the nearest file wins.
| Field | Role |
|---|---|
| minimumReleaseAgeHours | Minimum age in hours for registry versions. |
| registryUrl | npm-compatible registry URL for metadata (mirrors, Artifactory, Verdaccio). |
| allowedScripts | Package name → allowed script names. Does not remove ignore-scripts unless you change packageManagerDefaults. |
| allowedSources | Source types permitted (add git, tarball, url only if you intend to allow them). |
| allowedPackages | Names that skip policy checks entirely (warning emitted). |
| ciMode | Stored in config; default merges CI="true". Install and check flows do not branch on it yet. |
| packageManagerDefaults | Per-manager flags forwarded when spawning the tool; ignoreScripts defaults to true. |
CI and exit codes
0 — success or policy allowed. 1 — runtime or config error. 2 — blocked by policy. Use 2 like any other failing step in a pipeline.
safeinstall check
Evaluates direct dependencies only. On success, stderr includes: Check passed: no direct dependency policy violations found.
safeinstall init
Writes a starter safeinstall.config.json in the current directory. Refuses if the file exists unless you pass --force.
JSON output
Put --json anywhere in argv. Structured output goes to stdout; human-oriented messages stay separate. Field details are stable in the CLI version you install.
Exceptions
allowedPackages — exact name match skips checks (with a warning). allowedScripts — per-package lifecycle phases you accept for policy; SafeInstall may still forward ignore-scripts by default via packageManagerDefaults.
Limitations
- —Not a CVE scanner — pair with npm audit or other tools for vulnerability data.
- —Transitive dependency policy is not fully implemented.
- —Trust script comparison needs the previous resolved tree under node_modules.
- —Bun project installs are not fully lockfile-aware.
- —peerDependencies are not evaluated unless also declared as direct dependencies.
- —Ambiguous metadata leads to a block, not a silent allow.
Out of scope
SafeInstall is a pre-install guard, not a full platform.
License
SafeInstall is open source, released under the MIT license. Source code is on GitHub. Free forever for individual use. Team features (shared policy, org-wide enforcement) are a planned commercial addition — not part of the current CLI.
Provided as-is under MIT. Not a security guarantee. SafeInstall is a policy tool. It does not guarantee the safety of any package, does not detect all supply-chain attacks, and does not replace professional security review.