Releases: Mickdownunder/SafeInstall
Release list
v0.11.1 — trust-approve hardening + correct trust guidance
Security
safeinstall trust approvenow refuses Codex sessions. The human-approval gate blockedCI,CLAUDECODE, andCURSOR_AGENTbut had no Codex marker — a Codex session could approve its own trust-surface changes.CODEX_SHELLjoins the refusal list, with the first direct tests of the marker path.
Fixed
- Guard setup gives the correct Trust Surface next step — fresh projects are pointed at
trust lock, already-locked projects attrust status/trust approve; idempotent re-runs stay silent.
Changed
- Declared
mcpNamefor the official MCP registry. release:checkbuilds before testing (stale-dist e2e trap).
Published with Sigstore provenance from CI; the tarball reproduces byte-identically from the v0.11.1 tag.
v0.11.0 — one-command onboarding + Codex guard client
Added
safeinstall initis now one-command onboarding. Starter policy config → guard hooks for the agents actually present (.claude/,CLAUDE.md,.codex/,AGENTS.md,.cursor/,.cursorrules, or explicit--client claude,codex,cursor) → trust-surface lock over the result. Idempotent and fail-closed: an existing lock is never re-baselined — drift aborts init instead of blessing a tampered surface. New flags:--client,--no-guard,--no-lock,--mode warn|strict.- Codex is a first-class guard client.
safeinstall guard install --client codexregisters aPreToolUsehook in.codex/hooks.json; installs are rewritten through SafeInstall, unanalysable commands and registry runners fail closed (Codex has no ask decision yet). Users review the project hook once via/hooks.
Security
.codex/hooks.jsonand.codex/config.tomljoin the Agent Trust Surface enforcement zone.- E2E tests are isolated from host repo state (guard hooks spawn in fresh temp dirs).
Published to npm with Sigstore provenance from CI; the tarball reproduces byte-identically from the v0.11.0 tag.
v0.10.2 — guard parser security hardening
Security release
SafeInstall 0.10.2 hardens the coding-agent guard against shell-parser bypasses that could let raw package execution avoid policy evaluation.
Fixed
- Normalize package-manager, registry-runner, and wrapper launcher names for detection and rewriting.
- Analyze leading file-descriptor redirections before classifying commands.
- Parse supported wrapper options conservatively and fail closed on ambiguous embedded command syntax.
- Route remote
createandinitscaffolding through the registry-runner approval path. - Preserve SafeInstall routing for path-qualified package-manager invocations.
Hardening
- Added a permanent adversarial regression corpus.
- Added table-driven parser characterization and an independent reference detector.
- Added deterministic fuzz invariants and validated one million generated commands without an invariant violation.
- Split the security-critical parser into smaller reviewable modules without changing the CLI or hook contracts.
Upgrade
All users running 0.10.1 or earlier should upgrade:
npm install -g safeinstall-cli@0.10.2The npm package was published from the tagged commit through GitHub Actions with SLSA provenance. The release candidate passed 626 tests, package smoke validation, and CI on Linux, macOS, and Windows.
See GHSA-xrmc-c5cg-rv7x for impact and mitigation details.
v0.10.1 — leaner default install
Fixed
A default install no longer pulls sigstore and the MCP SDK. They were declared as optionalDependencies, which npm installs by default (skipped only when installation fails) — so a plain npm install safeinstall-cli pulled ~130 packages, dragging eval/network/shell/URL capability signals through the transitive tree and contradicting the "3 runtime dependencies, loads on demand" promise.
They are now peerDependencies marked optional in peerDependenciesMeta. A fresh consumer install now pulls only the three real runtime dependencies (npm-package-arg, semver, yaml) — verified: ~130 packages down to a handful.
The lazy-import paths are unchanged: enabling provenance.mode or running safeinstall mcp without the package still prints a clear install hint. A release-metadata test guards against regressing these back into installed dependencies.
No API or behavior change — a supply-chain tool should carry the smallest supply chain it can.
Full changelog: https://github.com/Mickdownunder/SafeInstall/blob/main/CHANGELOG.md
v0.10.0 — Agent Trust Surface
Added
Agent Trust Surface — SafeInstall now protects the files that program your AI agent and configure SafeInstall itself: safeinstall.config.json, the agent hook configs, AGENTS.md/CLAUDE.md/rules files, and .mcp.json. In the agent era these are the persistence surface — whoever edits them owns the next session.
safeinstall trust lock records a hash baseline; SafeInstall reconciles against it before guard decisions and every install/check. Three zones with proportionate responses: enforcement drift locks down, hidden Unicode (Trojan Source, incl. U+061C) always blocks, MCP drift and unpinned (rug-pull) servers block installs.
New commands: trust lock [--mode warn|strict] [--ci github], trust status [--require-lock] (read-only, exit 2 on drift), trust approve (human-gated), trust unlock (human-gated).
CI is the durable anchor. trust lock --ci github scaffolds a workflow that re-verifies the committed baseline on every pull request, with the CLI pinned to an exact version — tampering done on a compromised local machine does not survive review. For it to enforce, make it a required status check and require review of .safeinstall/ (CODEOWNERS).
Honest scope
Locally this is tamper-evident against mistakes and non-targeted tampering, not tamper-proof against a scheme-aware agent in your own account. The durable guarantee is CI re-verification of the committed lock on a machine the agent does not control.
Full changelog: https://github.com/Mickdownunder/SafeInstall/blob/main/CHANGELOG.md
v0.9.0 — agent guard: enforcement for AI coding agents
Added
Agent guard (safeinstall guard install) — the MCP tool is advisory; this is enforcement. SafeInstall registers as a pre-shell-execution hook for Claude Code and Cursor, so every shell command an agent runs is intercepted before execution.
The guard detects package installs — aliases (npm i, bun a), env prefixes, sudo/env/corepack wrappers, chained commands, pipes — and denies them with the exact rewritten command routed through SafeInstall: cd app && npm i axios becomes "run cd app && safeinstall npm install axios instead". A well-behaved agent self-corrects in one step, and the install then runs with full policy evaluation and scripts disabled.
Package runners (npx, pnpm dlx, bunx, npm exec) get a third verdict: ask — they execute registry code without install-time checks, so the user decides. Locally installed binaries are recognized and allowed without a prompt.
Fail-closed where it counts: installs hidden behind command substitution or variable expansion are denied with an explanation; ordinary non-install commands are never touched. No network, answers in milliseconds.
Also new: install-command aliases in the CLI (safeinstall npm i axios now works) and a global --config <path> flag with hard-error semantics for unreadable paths.
Fixed
- Security:
safeinstall npm install -- evil-pkgpreviously evaluated nothing while npm still installed the package. Post---tokens are now evaluated like any other spec. - GitHub Action
config-pathinput is now actually forwarded to the CLI. - Restored the missing
scripts/refresh-typo-squat-targets.mjsmaintenance script.
Full changelog: https://github.com/Mickdownunder/SafeInstall/blob/main/CHANGELOG.md
v0.8.0 — MCP server for AI coding agents
Added
MCP server (safeinstall mcp) — AI coding agents (Claude Code, Cursor, Windsurf, Cline) can now consult SafeInstall's full policy engine before suggesting or running any package install.
One tool: check_package — input a package name + optional version, get back a machine-readable verdict (allow or block) with reason codes, source repository, and age in hours. Backed by the same engine as the CLI — every check runs, including provenance continuity.
Without a project config file, the MCP server uses a secure preset: typo-squat detection and provenance continuity set to "block" (the agent use case wants maximum signal). When a config file is present, it is respected exactly.
Setup: one MCP config block + one agent rule snippet. See mcp/README.md for copy-paste configs for Claude Code, Cursor, and other MCP clients.
Full changelog: https://github.com/Mickdownunder/SafeInstall/blob/main/CHANGELOG.md
v0.7.0 — provenance continuity
Added
Provenance continuity — a per-package trust baseline that catches what npm structurally cannot.
npm verifies provenance at publish time but does not enforce continuity between versions. A compromised account can publish a version with no attestation (from a stolen token) or from a different repository, and npm raises no alarm. This is the dominant 2026 attack pattern (Mastra, the dormant-account republishes).
Continuity learns a per-package baseline from the provenance identity of recent versions and blocks deviations:
- provenance-downgrade — recent versions were attested, this one is not (the fingerprint of an account-compromise publish).
- identity-discontinuity — this version is attested from a different source repository than the established baseline.
Learned per package, so packages that never adopted provenance have no baseline and the check stays silent — no false positives. Reads npm's attestation metadata, so it works without the optional sigstore package. Opt in via continuity.mode.
The attack replay (pnpm replay mastra) now demonstrates the provenance-downgrade verdict — the catch npm defaults cannot make.
Honest limit: does not catch an attack delivered through a legitimately-compromised CI workflow with valid provenance from the real repository (the Shai-Hulud class).
Full changelog: https://github.com/Mickdownunder/SafeInstall/blob/main/CHANGELOG.md
v0.6.0 — sigstore is now optional
perf: make sigstore an optional dependency Move sigstore from dependencies to optionalDependencies. Users who do not enable provenance.mode (the default) no longer install sigstore and its ~160 transitive packages. This reduces installed package count from ~165 to ~5, improves install speed, and eliminates all six supply-chain warnings that Socket and Snyk flagged on the sigstore dependency subtree. When provenance.mode is enabled and sigstore is not installed, the lazy-loader now surfaces a clear error message telling the user to install it manually. For users who do install sigstore (either explicitly or because their package manager resolves optional deps by default), the behavior is identical to 0.5.0.
v0.5.0 — transitive dependency evaluation
Transitive dependency evaluation. SafeInstall can now evaluate the full lockfile dependency tree, not just direct dependencies — closing the biggest coverage gap, since most real supply-chain attacks reach a project through a transitive dependency.
Two checks run transitively, both read directly from the lockfile with zero extra registry calls:
- install-script — flags transitive packages that declare a lifecycle script (the ua-parser-js attack class). npm records this in the lockfile; pnpm lockfiles do not, so this check is npm-only for now.
- untrusted-source — flags transitive packages resolving from git, url, or tarball sources. Works for npm and pnpm.
Opt in via the newtransitiveconfig block (defaults to off, fully backward compatible):
{
"transitive": {
"mode": "warn",
"checks": ["install-script", "untrusted-source"]
}
}