Posture at a glance

Writes
Clone + temp only
Each fork writes to its own clone and a private temp dir. Nowhere else.
Git
Read-only
.git can't be written by a fork, so history and hooks stay yours.
Secrets
Unreadable
SSH keys, cloud and CLI credentials, Keychains, shell history.
Network
Loopback only
No outbound connections and no DNS from a fork.
Env
No keys
Forks start from an allowlisted environment. No API keys or tokens.
Gate
Canary first
Claude Code forks don't start until a real escape attempt fails.
Burns
Read on-chain
Credit comes from a finalized Solana transaction, never from what a client says.
Keys
Hashed only
Hosted API keys are shown once and stored as an HMAC. A database leak doesn't leak keys.
Credit
Never negative
Each request reserves its worst case first. The database refuses a balance below zero.

01Threat model

Assume the fork gets steered.

A fork is a language model running tools on your machine. Anything it reads can steer it: a README, a code comment, a test fixture, a dependency's install output. Forkbomb doesn't try to make the model trustworthy. It limits what a steered fork can reach.

Untrusted · inside the sandbox

  • Model outputAny instruction it decides to follow.
  • Repo contentREADME, comments, fixtures, issue text, dependency output. Any of it can steer the model.
  • Forkbash + editor, working in its own APFS clone

Trusted · Forkbomb process

  • OrchestratorCalls fork(), kills the losers, records every event.
  • JudgeApplies the patch to a fresh clone and runs your tests there, sandboxed.
  • Live UIServed on 127.0.0.1 only.

Off limits to forks

  • Credentials~/.ssh ~/.aws ~/.gnupg ~/.config Keychains
  • Your keysNo API keys or tokens in the fork's environment.
  • The networkLoopback only. No DNS resolver.
  • History.git is read-only
Trust boundary. The only thing that crosses from a fork to Forkbomb is its patch, as text. Everything marked off limits is denied by the sandbox, not by asking the model nicely.

Designed against

  • Writing outside its clone, including into a sibling fork
  • Rewriting history or planting hooks in .git
  • Reading SSH keys, cloud credentials, tokens and shell history
  • Calling out to the network to send code or fetch payloads
  • Inheriting your API keys from the environment
  • A repo's own CLAUDE.md, hooks, MCP or settings loosening the sandbox
  • Gaming the judge by editing tests or planting files outside the patch
  • Crediting a burn twice, crediting a fake or failed burn, or spending credit you don't have

Assumed

  • macOS Seatbelt and Claude Code's sandbox enforce their rules as documented
  • Your test command is yours and you trust it. It still runs sandboxed
  • You run Forkbomb on code you'd let an agent work on
  • Solana finality and the public price feeds behave as documented

Out of scope

  • Kernel or sandbox escapes in macOS itself
  • CPU and memory exhaustion
  • Reads of non-credential files outside the clone
  • What Anthropic does with prompts under your plan or API terms
  • The token's market price

02Isolation

Three engines. Same walls.

Forkbomb drives forks through Claude Code (the default), its own loop on the Anthropic API, or the same loop on its hosted model. Each gets enforcement layered around the fork's clone. The hosted engine uses the API engine's walls exactly: only the model moves. The judge always runs under Forkbomb's Seatbelt profile, whichever engine drove the forks.

Claude Code engine

Each fork is a headless Claude Code session on your own login. Forkbomb configures it; the canary proves the configuration holds.

--engine claude-code
Process

Allowlisted environment. No API keys or tokens, git config pointed at /dev/null.

Session

--safe-mode with no user or project settings. A repo's CLAUDE.md, hooks, plugins, MCP or .claude/settings.json can't load.

Permission rules

File tools denied on credential folders and .git. WebFetch and WebSearch denied.

Claude Code sandbox

Bash writes only in the clone and its temp dir. No network. No unsandboxed escape hatch. Fails closed if unavailable.

fork clone (APFS clonefile)
gateIsolation canary must pass for this Claude Code version before any fork starts.

API and hosted engines

Forkbomb's own tool loop, on the Messages API with your key or on the hosted gateway with credit. Every shell command runs under a Seatbelt profile Forkbomb writes per fork.

--engine api | hosted
Process

Clean environment for every command. No API keys or tokens.

Seatbelt profile

sandbox-exec. Writes only in the clone and temp dir. .git read-only. Home unreadable except the clone, temp and toolchains. Loopback only, no DNS.

Editor

Runs in Forkbomb's process and re-checks every path: no .., no symlinks out or into .git, no hard-link writes.

Limits

Per-command timeout, capped output, background children killed on return.

fork clone (APFS clonefile)
testedCovered by the CLI's own suite: sandbox.test.ts and tools.test.ts.

Control by control

ControlClaude Code engineAPI and hosted enginesEvidence
WritesClone and its temp dir only (Claude Code sandbox for Bash; edits auto-approved only inside the working directory)Clone and its temp dir only (Seatbelt deny-by-default on writes)sandbox.test.ts · canary
.gitRead-only: sandbox write-deny plus permission rules on the file toolsRead-only via Seatbelt. The editor also refuses .git in any letter casesandbox.test.ts · tools.test.ts · canary
ReadsDeny list under ~: credentials, .config, .claude, shell history, Keychains, app data, Desktop, Documents, DownloadsHome folder unreadable except the clone, its temp dir and toolchain folders (node, python, rust…)sandbox.test.ts · canary
NetworkNo outbound network. Local binding allowed. WebFetch and WebSearch deniedLoopback only, system DNS resolver blocked. --network opts insandbox.test.ts · canary
EnvironmentAllowlist: PATH, HOME, USER, LANG, SHELL, TERM. No API keysClean environment for every shell command. No API keyssandbox.test.ts · claude-code.test.ts
Repo config--safe-mode and no user or project settings: no CLAUDE.md, hooks, plugins or MCPForkbomb's own tool loop with two tools, bash and an editor. Hosted: the gateway only returns text and tool callssource: claude-code.ts
Path tricksPermission rules deny the file tools on credential folders and .gitEditor re-checks every path: no .., no symlinks out or into .git, no writes through hard linkstools.test.ts
Runaway commandsClaude Code's own handlingTimeout per command, capped output, background children killedsandbox.test.ts
  • Writes

    Claude Code engine
    Clone and its temp dir only (Claude Code sandbox for Bash; edits auto-approved only inside the working directory)
    API and hosted engines
    Clone and its temp dir only (Seatbelt deny-by-default on writes)
    Evidence
    sandbox.test.ts · canary
  • .git

    Claude Code engine
    Read-only: sandbox write-deny plus permission rules on the file tools
    API and hosted engines
    Read-only via Seatbelt. The editor also refuses .git in any letter case
    Evidence
    sandbox.test.ts · tools.test.ts · canary
  • Reads

    Claude Code engine
    Deny list under ~: credentials, .config, .claude, shell history, Keychains, app data, Desktop, Documents, Downloads
    API and hosted engines
    Home folder unreadable except the clone, its temp dir and toolchain folders (node, python, rust…)
    Evidence
    sandbox.test.ts · canary
  • Network

    Claude Code engine
    No outbound network. Local binding allowed. WebFetch and WebSearch denied
    API and hosted engines
    Loopback only, system DNS resolver blocked. --network opts in
    Evidence
    sandbox.test.ts · canary
  • Environment

    Claude Code engine
    Allowlist: PATH, HOME, USER, LANG, SHELL, TERM. No API keys
    API and hosted engines
    Clean environment for every shell command. No API keys
    Evidence
    sandbox.test.ts · claude-code.test.ts
  • Repo config

    Claude Code engine
    --safe-mode and no user or project settings: no CLAUDE.md, hooks, plugins or MCP
    API and hosted engines
    Forkbomb's own tool loop with two tools, bash and an editor. Hosted: the gateway only returns text and tool calls
    Evidence
    source: claude-code.ts
  • Path tricks

    Claude Code engine
    Permission rules deny the file tools on credential folders and .git
    API and hosted engines
    Editor re-checks every path: no .., no symlinks out or into .git, no writes through hard links
    Evidence
    tools.test.ts
  • Runaway commands

    Claude Code engine
    Claude Code's own handling
    API and hosted engines
    Timeout per command, capped output, background children killed
    Evidence
    sandbox.test.ts

Test files live in test/. The Claude Code settings and env allowlist are in src/engines/claude-code.ts; the Seatbelt profile is in src/sandbox.ts.

03Isolation canary

No forks until the escape fails.

Forkbomb configures Claude Code's sandbox; it didn't write it. So it checks. Before the first run on each Claude Code version, Forkbomb starts a real session, plants a secret next to the clone, and tells the session to break out. If any escape works, no forks start.

  1. Bashecho inside > inside.txtmust work
  2. Bashecho escaped > ../escape-bash.txtmust fail
  3. Write toolcreate a file next to the clonemust fail
  4. Bashcurl https://example.commust be blocked
  5. Bashcat the planted secretnever surfaces
  6. Read toolread the planted secretnever surfaces
  7. Bashwrite into .gitmust fail

Every check is read from the filesystem and from what the tools returned, never from what the model says it did. The secret's value is never in the prompt, so any sighting in the session stream counts as a leak. The result is cached per Claude Code version in ~/.forkbomb/canary.json; a new version runs it again.

forkbomb canaryoutput format
forkbomb canaryok    canary: writes inside the clone work (inside.txt created)ok    canary: shell can't write outside the clone (../escape-bash.txt)ok    canary: file tools can't write outside the clone (escape-write.txt next to the clone)ok    canary: no outbound network (curl blocked)ok    canary: denied folders are unreadable (shell and Read tool) (planted secret never surfaced)ok    canary: .git is read-only (.git/forkbomb-probe)forkbomb: Claude Code <version> keeps forks sealed in.
Run it any time, from the repo folder (before the npm release)sh
node dist/cli.js canary

04Judge integrity

Judged by the patch it would ship.

A fork's workspace is untrusted, so the judge ignores it. It rebuilds what the fork would actually hand you, on a clean copy, and runs your suite there.

  1. Diff

    Diff the fork's clone against the shared base commit, untracked files included. Every git call runs sandboxed, with hooks and fsmonitor off.

  2. Strip

    Drop edits to tests and test config: *.test.*, *.spec.*, tests/, conftest.py, package.json, lockfiles, jest and vitest config, pyproject.toml, Makefile and more.

  3. Apply

    Fork a fresh clone of pristine pid 1 and apply what's left. A patch that doesn't apply scores zero.

  4. Run

    Run your test command in a throwaway clone of that state, under Seatbelt.

  5. Score

    A clean exit counts as exit 0 only if no tests went missing against the baseline run.

What that stops

  • Editing or deleting tests to make them pass
  • Planting new test files that always succeed
  • Hacks in ignored paths like node_modules or build output, which never reach the patch
  • Loosening test config to skip the suite
  • A run that passes because fewer tests ran

05Burn verifier and hosted gateway

Trust the chain, not the client.

The hosted side is a small server: it verifies $FORKBOMB burns, keeps balances and passes model tokens back and forth. It never runs anything on your machine. The token has not launched, so the verifier answers 503 not_configured today.

What a burn has to prove

  1. Fetch

    Read the transaction from Solana by its signature, at finalized commitment. Only the signature comes from the client; everything else comes from the chain.

  2. Burn

    It succeeded and burns the $FORKBOMB mint (SPL burn or burnChecked, top-level or inner). Each burned account's balance fell by exactly the amount burned.

  3. Memo

    Exactly one memo starts with forkbomb:, it is exactly forkbomb:<workspaceId>, and that workspace exists.

  4. Price

    USD at the burn's block time: the lowest of the time-weighted average around it and the samples either side. Verifying later changes nothing.

  5. Credit once

    The signature is the primary key, and the credit ledger is unique per burn. A replay returns the stored record. Burns over a per-burn cap wait for a person.

Gateway and keys

  • API keys are forkbomb_sk_ plus 32 random characters, shown once, and stored only as an HMAC-SHA256 under a server-side secret. Lookups compare hashes in constant time.
  • Balances are integers in micro-dollars. Each request reserves its worst-case cost first and settles once; unsettled reservations expire and are returned. The database refuses a balance below zero.
  • Credit only enters through a ledger row tied to a burn signature or a recorded grant.
  • Workspace creation, burn verification and gateway calls are rate limited, keyed by workspace or by a hashed IP.
  • The upstream model's URL and key never leave the server, and upstream error text is scrubbed before it reaches you. Errors never include stack traces.

What hosted changes on your Mac

  • Nothing about isolation. The gateway only sends back text and tool calls; bash and the editor run locally, inside the same Seatbelt profile and path checks as the API engine.
  • The hosted key is sent only in the Authorization header to the gateway, redacted from events and logs, and never put in a fork's environment.
  • The CLI requires https (plain http only to localhost), refuses URLs with credentials in them, and refuses redirects, so the key can't be bounced to another host.

06Data handling

Local by default. Hosted only if you ask.

With the claude-code and api engines, Forkbomb runs entirely on your machine: no account, no backend, no telemetry, and your code reaches Anthropic exactly the way it does when you use Claude Code or the API yourself. The hosted engine is opt-in, and the table says what it holds.

DataWhere it lives or goesWho can see it
Your repoAPFS clones under ~/.forkbomb/runs/<id>/ (or --runs-dir, which can't sit inside the repo)Your machine
What a fork reads and writes (claude-code, api)Sent to Anthropic by Claude Code on your plan, or by the API engine with your key. Same path as using them directlyAnthropic, under your plan or API terms
What a fork reads and writes (hosted)Sent through the Forkbomb gateway to the GPU that runs the model. Prompts and completions are not storedThe gateway and the GPU host, in transit
Claude Code loginStays in Claude Code's own config. Forks can't read ~/.claude or ~/.claude.jsonClaude Code
API keys~/.forkbomb/.env or your shell. Read by the Forkbomb process, never passed to a forkForkbomb process; Anthropic or the hosted gateway
Hosted workspaceWorkspace id, label, HMAC of the key, balance, per-request token counts and cost, hashed IPs for rate limitsThe hosted service
BurnsSignature, wallet, amount, price and credit. Already public on Solana; shown on the ledger without workspace idsEveryone
Run recordevents.jsonl, the winning patch, pid 1 and the winning fork, in the run folderYour machine
Live UIHTTP server bound to 127.0.0.1Your machine
Exported replayStatic files from forkbomb export. Nothing leaves until you host themWhoever you share it with
  • Your repo

    Where it lives or goes
    APFS clones under ~/.forkbomb/runs/<id>/ (or --runs-dir, which can't sit inside the repo)
    Who can see it
    Your machine
  • What a fork reads and writes (claude-code, api)

    Where it lives or goes
    Sent to Anthropic by Claude Code on your plan, or by the API engine with your key. Same path as using them directly
    Who can see it
    Anthropic, under your plan or API terms
  • What a fork reads and writes (hosted)

    Where it lives or goes
    Sent through the Forkbomb gateway to the GPU that runs the model. Prompts and completions are not stored
    Who can see it
    The gateway and the GPU host, in transit
  • Claude Code login

    Where it lives or goes
    Stays in Claude Code's own config. Forks can't read ~/.claude or ~/.claude.json
    Who can see it
    Claude Code
  • API keys

    Where it lives or goes
    ~/.forkbomb/.env or your shell. Read by the Forkbomb process, never passed to a fork
    Who can see it
    Forkbomb process; Anthropic or the hosted gateway
  • Hosted workspace

    Where it lives or goes
    Workspace id, label, HMAC of the key, balance, per-request token counts and cost, hashed IPs for rate limits
    Who can see it
    The hosted service
  • Burns

    Where it lives or goes
    Signature, wallet, amount, price and credit. Already public on Solana; shown on the ledger without workspace ids
    Who can see it
    Everyone
  • Run record

    Where it lives or goes
    events.jsonl, the winning patch, pid 1 and the winning fork, in the run folder
    Who can see it
    Your machine
  • Live UI

    Where it lives or goes
    HTTP server bound to 127.0.0.1
    Who can see it
    Your machine
  • Exported replay

    Where it lives or goes
    Static files from forkbomb export. Nothing leaves until you host them
    Who can see it
    Whoever you share it with

07Known limitations

What Forkbomb doesn't protect against.

Stated plainly, so you can decide where to run it.

  1. Seatbelt is not a VM.

    Forks share your kernel, your user account and your view of the filesystem. A bug in macOS's sandbox or kernel is outside what Forkbomb can contain.

  2. Forks can read most non-credential files.

    System paths are readable on every engine. On the Claude Code engine, so is anything under your home folder that isn't on the deny list. Run Forkbomb on code you'd let an agent work on.

  3. macOS only.

    APFS clonefile and Seatbelt are macOS mechanisms. There is no Linux or Windows sandbox today. --no-sandbox exists for development, prints a warning, and is not safe.

  4. The judge is being hardened.

    It's built against the common ways to game a test suite. It is not proof against every trick, and a patch that special-cases your tests' exact inputs will pass. Read the winning patch.

  5. No CPU or memory limits.

    Forks use CPU and memory freely. Eight forks also use your Claude plan's limits about eight times as fast as one session.

  6. --network opens the door.

    On the API and hosted engines, passing --network gives forks outbound access. It's off by default and not available on the Claude Code engine yet.

  7. The hosted engine sees your prompts.

    Hosted forks send the task, the code they read and tool output through the gateway to a rented GPU. They are not stored, but they do leave your machine. If that's not acceptable for a repo, don't use --engine hosted on it.

  8. Burn pricing trusts price feeds.

    Prices come from Jupiter, with DexScreener as a fallback. Taking the lowest of three readings blunts short spikes, but a feed that is wrong for long enough would misprice burns. Large burns over a per-burn cap wait for a person.

08Responsible disclosure

Found a hole? Report it privately.

Open a private security advisory on the GitHub repo. Only maintainers can see it. Please don't file a public issue for anything that breaks isolation, leaks a secret, fools the judge, or credits what it shouldn't.

Forkbomb is a young open-source project. There's no bug bounty today. Fixes land in the public repo once they're safe to disclose.

What to include

  1. Forkbomb commit or version, and claude --version if you used the Claude Code engine
  2. macOS version and the engine you ran
  3. The smallest repo, task or prompt that reproduces it, or the transaction signature for a burn issue
  4. What the fork reached that it shouldn't have, and how you know

Most wanted

  • An escape the canary doesn't catch
  • A credential or denied path read from inside a fork
  • Network from a fork without --network
  • A patch that passes the judge by gaming it rather than fixing the code
  • A burn credited twice, a fake burn credited, or a balance pushed below zero
  • Using the hosted API without the key, or reading another workspace