Arrange Act Assert

Jag Reehals thinking on things, mostly product development

How sandbox runs risky installs in a throwaway container

15 Jun 2026

@jagreehal/sandbox-node runs your npm install in a throwaway container that can see your project and the registry, and nothing else.

Install scripts still run. node-gyp still builds. Your SSH keys, npm token, cloud credentials, and .env are not in the box, so a malicious dependency has nothing to steal and nowhere to send it.

The one-picture version

Put sandbox in front of the command you already run:

sandbox npm install
sandbox pnpm add zod
sandbox npm run dev

Under the hood the risky code runs in a container that can reach your project files and the npm registry. It cannot reach your home directory, your credentials, or anywhere else on the internet. When the command finishes, the box is deleted and your installed dependencies stay behind.

This is install-time containment, not a general sandbox. It targets the one moment that the previous post is about: when untrusted dependency code executes with your access.

Why this is worth it

You do not have to stop using normal package managers. You do not have to disable install scripts and break native modules. You do not have to read every transitive dependency before you clone a repo.

You keep the workflow you already use. The difference is that install-time code runs somewhere with no secrets to steal, nowhere to phone home, and fewer places to persist. Same workflow, smaller blast radius.

That gives you a handful of practical benefits:

One attack path, end to end

You add a package. One dependency under it ships a postinstall script. During install, that script reads ~/.npmrc, checks ~/.aws/credentials, writes a hook into .git/hooks, and makes an HTTPS request to a host you have never heard of.

On your host, that works because the script runs as you. In sandbox, each step hits a different wall. The credentials are not mounted. The common persistence paths are read-only. The network request has no route unless you allowed that host.

Three layers: check it, contain it, catch it

A supply-chain worm needs three things to work: a version fresh enough to still be live, something worth stealing, and a way out. sandbox works in three layers that line up against those, so no single bypass defeats it: it checks a package before the box runs, contains the code while it runs, and catches anything that tries to get out.

Check it before the box runs

Before any dependency code executes, sandbox vets what you are about to pull. This is the part that reaches out to external sources to confirm there are no known issues:

Contain it while it runs

A check is a signal, not a guarantee, so the vetted install still runs inside the throwaway box. Inside, there is nothing to take and no way out:

Catch it and prove the box held

The last layer is evidence: knowing something tried, and being able to show it did not get out.

It works across npm, pnpm, yarn, and bun, plus runners like npx, bunx, node, tsx, and vite. Anything that pulls new versions goes through the same checks, so update, upgrade, and audit fix are covered too, not just first install.

One tool instead of a toolchain

None of these checks is a new idea on its own. You could assemble most of them from separate tools: one to review packages before install, one to block known malware, one to enforce a minimum release age, and a devcontainer for isolation. Then you wire them together, keep four configurations in sync, and hope every developer set them up the same way.

sandbox puts review, age-gating, malware-blocking, and containment behind one prefix and one config file. You get the safety and the developer experience in one place, instead of orchestrating a toolchain and hoping it holds.

That single file is also what turns this from a personal habit into a team decision. Commit sandbox.config.json and the boundary is reviewed in a pull request, like any other code. sandbox verify enforces it in CI so nothing merges around it, a personal override that loosens it is flagged on every run, and a badge can advertise that installs go through it. Everyone installs against the same policy, whether or not they remember to.

Limits

You should know the edges before you adopt it.

Your source tree stays writable during a normal install, because package managers need a writable root and pnpm writes temp files there. A malicious dependency can still overwrite a file in src/ during install. You will see it in git diff, and --frozen makes the whole tree read-only on every package manager except pnpm. What sandbox blocks is credential theft, persistence, and exfiltration. It does not promise source immutability unless you ask for it.

Anything you grant is in scope on purpose. Forwarding a private-registry token with --env NPM_TOKEN, mounting a path, or turning network on are explicit opt-ins. Grant the minimum.

It needs Docker (or a Docker-compatible engine like OrbStack or Podman) and runs on macOS or Linux, or Windows under WSL2.

How it sits next to other tools

Devcontainers give you a full containerised workspace, but a devcontainer does not make npm install safe: inside it, the install still runs with whatever the container can reach. sandbox fills the install-time gap a devcontainer leaves open, and it can generate the devcontainer for you when you want a persistent environment. That is composition, not competition.

The same is true of Claude Code's built-in OS sandbox: run that for the agent's whole blast radius, and sandbox for the supply-chain surface on top.

Bottom line

sandbox does not try to read the dependency code in time, recognise the package, or out-guess the release timing. It runs the install in a box that has nothing worth stealing and no way to send it. Same workflow, smaller blast radius.

The next post covers setup: getting the sandbox command, the one-button onboarding, making it automatic so you never type the prefix, and wiring it into agents and CI.

Run installs in a sandbox

  1. npm install runs code you never read
  2. How sandbox runs risky installs in a throwaway container (this post)
  3. How to put sandbox in front of npm, pnpm, yarn, and bun
security npm pnpm supply-chain sandbox tooling safe-installs-series