Build CodeSandbox

KINDAreplaces $12/mosaves $144/yrback to the verdict

0%0 of 17 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

A hosted development environment service where the whole engineering problem is running arbitrary untrusted code quickly, safely and cheaply, and where the difference between a good product and an incident is entirely in isolation and resource control.

estimated effort multi-daythe files for this build are in the project pack

IsolationOne sandbox per environment with no shared kernel surface where possibleStartupSnapshot and restore rather than cold bootFilesystemA layered image with a writable overlay per environmentNetworkingEgress denied by default with declared allowancesRuntimeTypeScript control plane with a container or microvm layer

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. installfree

    Why Runs the control plane.

    Get it nodejs.org, or nvm install 22. open ↗

    Verify node --version prints v22 or higher

  2. installfree

    Why The isolation boundary is the product, and choosing a runtime without understanding its escape history is choosing a boundary you cannot reason about.

    Get it A runtime with a documented isolation model, and read its known weaknesses before building on it.

    Verify A hostile workload cannot reach the host or a neighbour

  3. have readythe price of one small instance

    Why You will be running deliberately hostile code against your own isolation, and doing that on a machine with anything else on it is unwise.

    Get it A dedicated machine or an isolated cloud instance with nothing else on it and no credentials attached.

    Verify The machine holds no credentials and hosts nothing else

  4. decidefree

    Why Free compute attracts mining, outbound traffic and content hosting within days, and the response path has to exist before the first environment is public.

    Get it Decide the four ceilings, what triggers a suspension, and how someone reports abuse to you.

    Verify A written policy exists with a reporting route and the ceilings are configured

  5. have readyfree

    Why Isolation claims are only meaningful when something has actually tried to break them, and writing those attempts is part of the build rather than an audit afterwards.

    Get it Write environments that attempt host access, neighbour access, control plane access and egress to an undeclared destination.

    Verify Four hostile environments exist and all four are contained

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- environments(id, owner_id, template_id, state, created_at, last_active_at, suspended_reason)
- snapshots(environment_id, id, storage_key, bytes, taken_at) · what makes a restart fast
- templates(id, name, base_image_ref, default_resources_json)
- resource_limits(environment_id, cpu_millis, memory_bytes, disk_bytes, egress_bytes_per_hour)
- usage(environment_id, window_start, cpu_millis, egress_bytes, disk_bytes)
- egress_rules(environment_id, ordinal, destination, allowed) · default deny, allowances explicit
- suspensions(environment_id, reason, at, evidence_json, lifted_at)
- An environment is suspended rather than deleted when it breaches a limit, because the usual cause is a runaway loop rather than malice and the owner's work should survive.

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
DATABASE_URLsecretrequiredpostgres://localhost:5432/environmentsControl plane state. Never reachable from inside an environment.
EGRESS_DEFAULTrequireddenyPresent as a constant. A blocklist is always incomplete.
CPU_MILLIS_LIMITrequired2000Per environment. Exceeding suspends rather than destroys.
EGRESS_BYTES_PER_HOURrequired1073741824The limit that catches mining and outbound traffic first.
HIBERNATE_AFTER_MINUTESrequired30Releases compute while preserving the filesystem.
FORK_EXCLUDE_PATHSrequired./config/fork-exclude.txtSecret-bearing paths, excluded so a shared template does not leak credentials.

The build, in order

  1. An environment that cannot see out

    Code inside a sandbox reaches nothing it was not given.

    1. Nothing in the environment belongs to the platform.

      Files src/sandbox/tests/escape.test.ts

    2. A blocklist is always incomplete and abuse finds the gap first.

      Files src/network.ts

    3. Host filesystem, control plane, neighbour environment.

      Files tests/escape.test.ts

    done when · tick each as it passes
    watch out
    • Allowing egress by default and blocking known-bad destinations means the first abusive environment finds the destination you did not list, and outbound attack traffic from your address range is a problem that arrives as an abuse report. Deny by default and allow explicitly, which is the only version that holds.
  2. Starting fast enough to be used

    An environment is ready in a couple of seconds, not a minute.

    1. Installing dependencies at start costs every environment the same minute.

      Files src/snapshots.ts

    2. A hundred environments from one template should not be a hundred copies.

      Files src/images.ts

    3. Created and usable are different moments and only one matters.

      Files src/metrics.ts

    done when · tick each as it passes
    watch out
    • Installing dependencies at start means every environment pays the same minute, and a development environment that takes a minute to open is one people stop opening. Snapshot after the environment is warm and restore from that, so the cost is paid once per template.
  3. Limits that stop a runaway

    A loop consuming everything is contained and its owner keeps their work.

    1. Processor, memory, disk and egress. Egress is the one people forget.

      Files src/limits.ts

    2. Most breaches are a loop, not abuse. The work should survive.

      Files src/suspend.ts

    3. A resource hog must not degrade anyone else.

      Files tests/noisy-neighbour.test.ts

    done when · tick each as it passes
    watch out
    • Destroying an environment that breached a limit loses the owner's work, and the overwhelming majority of breaches are an accidental infinite loop rather than abuse. Suspend, preserve the filesystem, and say which limit was hit so the person can fix their code.
  4. Work that survives closing the tab

    An environment resumes with the changes you made.

    1. It is the user's work and it is not in version control yet.

      Files src/overlay.ts

    2. People leave tabs open for days assuming safety.

      Files src/hibernate.ts

    3. Browsers close, networks drop, and neither should corrupt anything.

      Files src/overlay.ts

    done when · tick each as it passes
    watch out
    • Reclaiming an idle environment by destroying it loses uncommitted work, and people leave tabs open for days assuming their changes are safe. Hibernate by persisting the overlay and releasing the compute, so resuming is fast and nothing is lost.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more dev tools.