Typosquatting
A package named react-domm waits in the registry. One typo and its
postinstall hook reads ~/.ssh/id_rsa to a remote endpoint.
npm install. Stop trusting it.A sandboxed runtime for npm install, npm run dev, and friends. Your project
dependencies execute in a micro-VM with zero access to your home directory,
credentials, or anything else outside the project folder.
npm install -g @fendsh/cliRequires macOS 13+ on Apple Silicon. The CLI is open source — browse the source.
Coming after the Mac MVP soaks. The Rust CLI shares the guest agent; Firecracker handles the sandbox. Follow on GitHub to be notified.
WSL2 is the planned isolation layer. Same CLI surface, same .fend.toml. Tracking on the roadmap.
The threat
npm install runs arbitrary code as youThree classes of attack are now routine in the npm ecosystem. All three end the same way — arbitrary code, executed under your user, with full access to everything you can touch.
Typosquatting
A package named react-domm waits in the registry. One typo and its
postinstall hook reads ~/.ssh/id_rsa to a remote endpoint.
Maintainer takeover
A trusted dep changes hands and its next minor release is malicious. Happened
to event-stream, to colors, to node-ipc. Will happen again.
Dependency confusion
A private package name gets registered in the public registry. Your install silently pulls the attacker’s version.
What fend actually blocks
postinstall can’t reach what isn’t thereWithout fend
> [email protected] postinstall> node ./steal.js
✓ exfiltrated /Users/you/.ssh/id_rsa✓ exfiltrated /Users/you/.aws/credentials✓ added launchd persistence
added 1 packageWith fend
fend: ready (0.8s)
> [email protected] postinstall> node ./steal.js
Error: ENOENT /Users/you/.ssh/id_rsaError: ENOENT /Users/you/.aws/credentialsError: EACCES launchctl
added 1 packageSame package, same script — no SSH keys to steal because the VM never had access to ~/.ssh.
Recording of the live demo coming soon.
How it works
your shell micro-VM (Linux) ────────── ──────────────── $ fend npm install ──┐ ┌─ npm install runs here │ │ ▼ │ • sees /workspace (= your project dir) [ fend ] │ • sees /root/.npm (host npm cache) │ │ • sees the network boots / reuses ─────────►│ • sees nothing else from your Mac warm VM (~800ms │ cold, ~5ms warm) │ /home/you/.ssh → does not exist │ │ /home/you/.aws → does not exist ◄───────── stdout/stderr │ /home/you/Library → does not exist │ └─ writes node_modules/ back via VirtioFSBuilt on Apple Virtualization.framework — the same hypervisor OrbStack and Apple Containerization use. Sub-second cold boot, instant warm dispatch, auto-pause after 5 min idle.
Two layers of defense
Micro-VM sandbox
Every command runs inside a per-project Linux micro-VM with VirtioFS mounting only your project directory. The VM cannot read ~/.ssh, ~/.aws, ~/Library, ~/.gnupg, or any .env file outside the project.
Boots in ~800ms, warm dispatch in ~5ms, pauses after 5 min idle.
OSV.dev audit on every install
Before lifecycle scripts run, fend queries OSV.dev for
known advisories against your package-lock.json — one batch round trip,
cached per advisory.
Blocks malware and critical outright. Prompts on high. Configurable in .fend.toml. fend audit --fix upgrades and writes overrides for you.
Sandbox boundary
~/.fend/cache/npm/)TERM, LANG, LC_*, EDITOR, GIT_AUTHOR_*, GIT_COMMITTER_*, COLORTERM, NO_COLOR, FORCE_COLOR~/.ssh/ — SSH keys~/.aws/ — AWS credentials~/Library/ — Keychain, browser data, cookies~/.gnupg/ — GPG keys.env files outside the project directoryAWS_*, GITHUB_TOKEN, NPM_CONFIG_*, ANTHROPIC_*, CLAUDE_*, HTTP(S)_PROXY, SSH_AUTH_SOCK env varsNeed to inject a token explicitly? Use —env KEY=VALUE or —env-file — values stay in process memory, never written to the VM filesystem. Full reference →
vs. the alternatives
| Sandboxes execution | Catches known CVEs | Works with npm/bun/pnpm | Native IDE experience | |
|---|---|---|---|---|
| fend | ✓ | ✓ (OSV.dev) | ✓ | ✓ (VirtioFS) |
| npm audit | ✗ | partial (npm DB) | ✓ | ✓ |
| Socket.dev | ✗ (alerts only) | ✓ | ✓ | ✓ |
| Deno permissions | runtime flags | ✗ | Deno-only | ✓ |
| Dev Containers | ✓ | ✗ | ✓ | remote-extensions only |
| Just running it | ✗ | ✗ | ✓ | ✓ |
fend is complementary to detection tools like Socket.dev. Detection tells you something looks suspicious. fend makes it not matter if it’s malicious.
Quickstart
# 1. Installnpm install -g @fendsh/cli
# 2. Use it as a prefixfend npm installfend npm run dev
# 3. Or hook your shell so you can drop the prefixecho 'eval "$(fend hook zsh)"' >> ~/.zshrcfend on # npm/bun/pnpm/yarn/node now route through fendnpm install # sandboxedfend off # back to normal