snib

status: pre-release. The author is dogfooding it on real client work before launch.

Disposable dev environments for the truly paranoid.

You want to run an npm install, a build script, or an AI coding agent without handing it your keys. snib runs it in a throwaway Linux VM on your Mac, and the VM holds placeholders, not real credentials.

A broker outside the VM swaps a placeholder for the real value on the wire, only toward the destination you approved in the manifest, and records the request in a host-side audit log the VM can't reach. The enforce tier adds a host firewall that blocks the VM's direct egress.

$ snib run -- npm install          # observe tier: no sudo, audited
$ snib run --enforce -- claude     # enforce tier: host firewall on

what a compromised dependency sees

Say a postinstall script goes hunting, the way the nx "s1ngularity" malware did when it drove victims' own Claude Code CLIs to collect secrets. Inside a snib workspace:

If malware steals the placeholder, it has not stolen the credential.

the evidence

These seven rows are machine-checked on every gate run from the host, against a throwaway sentinel, never a real credential. Each absence row is gated on a positive control, so a broken flow fails red instead of passing green by accident.

rowwhat it provesresult
cred.proxy_rewriteplaceholder→real fired upstream, over verified TLSPASS
cred.scope_enforcedthe same placeholder sent to an off-scope host stayed a placeholderPASS
cred.scope_identitya spoofed Host header over a raw-IP authority did not injectPASS
cred.no_reflect.plaina reflecting upstream's response reached the caller with the scanned encodings (literal, base64, hex, URL) redactedPASS
cred.no_reflect.gzip…including a gzip-compressed reflectionPASS
cred.secret_not_loggedthe sentinel, in all scanned encodings, is absent from the checked host log surfacesPASS
cred.dns_beacon_inertthe guest never held the value, so a DNS beacon can carry only the placeholderPASS

Run them yourself on a laptop, no VM, no sudo: bash tools/gate/cred-gate.sh --driver host. The full gate runs the same assertions with requests originating inside the enforced VM.

how it works

layermechanism
Secrets The manifest declares key, a ref into 1Password (or an env: value), and a required to destination. snib resolves the ref host-side, arms an auditing proxy, and the guest gets a placeholder. Injection happens on the wire, bound to the verified TLS identity of the named destination. Responses are scanned for the value in literal, base64, hex, and URL encodings — compressed bodies included — and redacted before the guest sees them.
Egress The enforce tier backs the workspace with a host firewall chokepoint, so a process that tries to leave without going through the broker is dropped. A deny-by-default allowlist is rendered from the manifest's egress.allow (strict host globs; schemes, ports, paths, and non-ASCII are rejected, never coerced). Arming the broker with that allowlist on run is the next enforcement step — see the limits below.
Isolation A NixOS guest on Apple's Virtualization framework (via vfkit): separate kernel, separate network identity. Mounts default to read-only. The manifest lives inside the project, so a compromised guest could edit its own grants — which is why every grant change invalidates a host-owned approval hash, and run refuses until you re-approve from outside.

snib itself is Bun + TypeScript with zero npm dependencies (the broker is mitmproxy). 200 unit tests cover the manifest parser, approval gate, allowlist renderer, and secrets path.

what it doesn't stop

Known limits, current as of this build:

compared to

Cloud agent sandboxes (E2B, Daytona, Modal) The sandbox runs on your machine; the workspace is not uploaded to someone else's cloud. And the secrets stay outside the sandbox rather than inside it.
Short-window secret brokers Some brokers hand the agent a real credential for a bounded window. snib's workspace gets a placeholder; the broker injects the real value outside the VM, only toward a verified destination.
OS sandboxes (seatbelt, sandbox-runtime) A sandbox inside your host shares its kernel, DNS, and network identity. snib puts the run in a guest VM with its own kernel and its own network identity.
Docker Containers share the host kernel. They also don't help when the real credential is available as an environment variable; snib gives the guest a placeholder instead.

why now

2025–26 turned "malicious dependency steals developer credentials" from a hypothetical into a recurring failure mode: the tj-actions/changed-files compromise dumped CI secrets across 23,000+ repos; the nx "s1ngularity" attack drove victims' own AI CLIs to hunt their secrets; chalk/debug put attacker code in packages with ~2.6 billion weekly downloads; the Shai-Hulud worm self-replicated through npm twice. Each case depended on the same weakness: real credentials reachable from code that had just run.

install

Not yet. If you want to be told when the repo opens, email james@cloudship.co.uk — you'll get exactly one email, when it ships.