Skip to main content
Two things a partner engineer should learn before integrating rather than after: the ceiling on what your provider may claim, and the guarantees that do not survive a network hop. Both are below, stated as limits rather than as caveats. Read Sandbox providers for the concept and the capability envelope, and Sandbox provider contract for the operations.

The grading rule

A third-party sandbox provider is pinned to advisory_filter. security_boundary is earned only through a conformance matrix Checkfu runs itself. egress_certification is the capability-honesty grade for one exact (provider, provider_revision) pair. It is a total order: A SandboxProfile’s allowlist policy may name required_egress_certification: "advisory_filter" | "security_boundary". Selection compares the requirement against the selected provider’s advertised grade and fails typed before any provider work starts. It never infers, upgrades, or averages, and unsupported is not a spelling a policy may require — a policy may not ask that nothing apply its own restriction.
An allowlist policy that names nothing still requires advisory_filter. The requirement is opt-in, never retroactive, so an omitted field falls to the floor an allowlist profile has always been admitted under — not to unsupported. The practical consequence for a day-one provider: advertising egress_certification: "unsupported" means no allowlist profile can ever select you, whether or not any profile mentions the requirement. none and unrestricted policies are unaffected, because they declare no destination restriction for a grade to be honest about.
Two structural details are worth copying into your own thinking. The field lives only on the allowlist member of the policy union, so “require a boundary while asking for unrestricted egress” is unrepresentable rather than merely rejected. And the requirement is optional and omitted by default, so no retained profile changes meaning — or template digest — when the field was added. The grade is not purchasable by configuration, and it is not inferable from anything else. In particular it is deliberately independent of enforcement.network_policy: a provider declaring provider_attested there has said “I own my configured filter,” which is a different and much weaker claim than D130’s fact set. That independence is test-pinned precisely so security_boundary can never be back-derived from an attestation.

The five facts, and the three that cannot be self-attested

A security_boundary receipt must prove all five together. A receipt missing one certifies nothing: Two of the five — exact_destination_match and redirect_recheck — are positive and enumerable. Hand the implementation a host and a port and watch it accept or refuse; hand it a redirect and watch it recheck the target. Anyone can construct those inputs, and the observations are about what the code does, not about what it lacks. The other three are not that shape, and this is why the rule is a structural one rather than a judgment about partners.
“Un-self-attestable” does not mean unprovable. Checkfu’s own Docker matrix proves two of these three — it owns the resolver and it owns the topology, so it can construct the adversarial cases. The claim is narrower and sharper: they cannot be proved by the party making the claim about itself, because each is a statement about a case that party would have to choose to construct, about something it does not hold, or about paths it did not think of. That is why the grade is earned through a matrix Checkfu runs rather than through a document you send.

connect_time_public_address

The claim is negative, per-connection, and about a moment that has not happened yet: every resolved address, on every connection, at connect time, was public. Testing it requires controlling the answer — you must make an admitted hostname resolve to a private address and observe the refusal. Only a party that owns the resolver can construct that case, and a self-attester constructs only the cases they thought of. DNS rebinding is precisely an attack on the gap between check and connect; a statement cannot close a gap. The sharper problem is that the obvious test passes against an implementation that does not implement the fact. Checkfu’s own matrix owns the private-address answer end to end through Docker’s embedded DNS, and its target deliberately accepts TCP on 443 — because the guard answers 403 for an upstream connection error exactly as it does for a policy denial. Point that case at a host with nothing listening and it goes green against a guard whose connect-time classification had been deleted. With a live listener it reds. A self-attester has no reason to build the harder version, and no way to prove they did.

authority_separation

This is a claim about what the provider does not have — that the workload egress edge holds no plane credential, and that workload and plane traffic ride separate sealed authorities. A party cannot attest to its own non-possession. The evidence for “I do not hold this” is the absence of something inside a boundary only that party can see. Docker is at least architecturally positioned to prove it rather than assert it: two containers on two routes, and a guard whose environment is compiled by the Runner, so its contents are Checkfu-authored fact rather than a provider report. Note that positioning is not proof, and Checkfu does not claim it as one — authority_separation is one of the two facts the owned Docker matrix still does not establish, because it needs a real Run through the transport. The difference between “structurally provable” and “proved” is exactly the difference this grade is measuring. The rule is not aimed at strangers, and E2B is the proof. E2B validates the two authorities separately and then flattens them into the provider’s single allowOut list, because the provider API exposes no authority dimension at all. That fact alone holds a shipped first-party integration at advisory_filter. A partner is being held to a bar Checkfu already failed to clear on one of its own providers.

default_deny

The claim quantifies over the complement of the implementation: when any other fact is absent, nothing gets out. A suite the implementer wrote enumerates the paths the implementer thought of — which is exactly the set default-deny exists to backstop. Checkfu’s matrix includes a case that only exists because the tester assumed the workload would be hostile to the mechanism: no route at all when the workload simply ignores the proxy environment variables. That case is not discoverable from a cooperative reading of your own design.

What a signature proves

Receipts travel as a detached Ed25519 signature over domain-separated canonical bytes (checkfu.sandbox-egress-conformance.v1) from an attester named in the reviewed SANDBOX_EGRESS_CONFORMANCE_ATTESTERS set. That mechanism proves authorship and integrity: this exact statement came from this exact key and was not altered. It does not, and cannot, prove the statement. Adding a partner key to the attester set would not make a partner’s claims true — it would make Checkfu’s reviewed set include a signer whose claims Checkfu has not verified, which is the same thing as deleting the grade.

The current posture

SANDBOX_EGRESS_CONFORMANCE_ATTESTERS is empty.
No provider has security_boundary today — including Checkfu’s own. A security_boundary-requiring profile is currently refused by every provider. That is the decision working, not a gap: the grade is not purchasable by configuration, so the requirement stays unsatisfiable until an owned matrix runs and the release authority publishes an attester key in a reviewed change.
Where the in-tree providers actually sit: The Worker-hosted runner’s cloud-vendor adapters (Daytona, E2B, Vercel) sit at advisory_filter too, and their grade does not carry over from the identically named Node adapters: a receipt for checkfu:daytona-provider@2 says nothing about a *-worker-provider@* revision. Same provider name, different exact revision, separate evidence. So the third-party rule is not a stranger tax layered on top of a privilege Checkfu enjoys. It is the same rule, and Checkfu is currently on the same side of it.

The enforcement ceiling gap

Egress grading is the solved half of the honesty problem. The unsolved half is larger, and a partner should know it is open because it gates when this seam can be published. SandboxEnforcement — the nine-axis authority statement — is not a field of RunnerProviderCapability. The server-owned enrollment ceiling that intersects a Runner’s drivers, launch_kinds, tiers, platforms, network_modes, retention_modes, mount_kinds, runtime_assurances, snapshot_clone, snapshot_custody, and package_materialization therefore never touches the enforcement statement. Nor is enforcement the only axis that escapes it. RunnerProviderCapability also omits egress_certification (compared Runner-locally at selection), image_mode, fixed_base_images, package_managers, snapshots, and list_dir — every one of them declared Runner-locally with nothing in the enrollment able to contradict it. list_dir is the one that reaches a customer-visible outcome on its own. It gates memory writeback under D38, so a provider admitted for memory mounts can decline writeback Runner-locally and the Run records a visible skip — correct behavior, but the enrollment that admitted the mount never had a say in it. In-tree that is harmless: the only authors are Checkfu’s own adapters, and runner_enforced is true because the Runner set the flags itself. It stops being harmless the moment a stranger authors one. The concrete consequence is on the openProcess evidence cross-check. Today it compares a provider’s per-process evidence.enforcement against capabilities.enforcement — where the right-hand side is a constant compiled into the trusted Runner. That is provider statement versus Runner-owned fact. Over a wire, both sides are authored by the same partner, and the comparison degenerates into a self-consistency check. It still catches a partner whose per-process evidence disagrees with its own advertisement, which is a real class of bug. It catches nothing about physical isolation. Three existing mechanisms close it, and all three are reuse rather than invention: cap the authority vocabulary by placement so a non-Runner may not say runner_enforced; add enforcement to RunnerProviderCapability and intersect it with the operator-issued enrollment ceiling every other axis already uses; and bind the envelope to an attributable signed materialization statement. None of that makes the claim true. It makes it ceilinged and attributable, which is the most a wire can offer — physical truth still comes from a Checkfu-run matrix, exactly as egress_certification already requires.
Publishing the provider seam before that ceiling lands would ship a weak tier that nothing in the system records as weak. That is the failure the host-process tier was explicitly designed to avoid, and it is why this gap is called blocking rather than pending.

What openProcess costs across a wire

openProcess is the one member of the contract that is a live object rather than a value. It does cross a network boundary — the design is complete and a spike drove a real ACP agent across it, including a connection severed mid-turn — but it crosses at a stated cost. Three guarantees the in-process handle makes do not survive, and all three are named here rather than engineered around.

Real stdin backpressure becomes a credit window

In-process, the writable stream handed to the driver is the child’s actual OS pipe: a slow guest slows the writer, and the flow control is physical. Across a wire it cannot be. TCP or HTTP/2 flow control on the Runner↔provider hop does not reach the provider↔guest stdin pipe — the provider must accept and buffer. So backpressure becomes an explicit credit window: the provider grants input_credit bytes at open and refreshes it on every accepted write, the Runner may not have more than that outstanding, and overrun is refused as input_buffer_full and retried after the next grant. When the guest’s stdin pipe blocks, the provider simply stops granting. This is a new failure mode that does not exist today, and the exposure is not small. An earlier revision of this page said it was, citing a 1 MiB frame ceiling and a one-shot driver that writes a single prompt and closes. Both citations were wrong and are withdrawn:
  • ACP_MAX_FRAME_BYTES bounds the other direction. It is read in exactly one place, inside boundAcpOutput, which is applied to output and only to outputinput is passed raw. There is no frame bound on the stdin direction anywhere in the repository.
  • The one-shot reassurance describes a harness nobody can currently launch. oneshot-v1’s sole catalog entry is availability: "blocked"; every other packaged entry is acp-v1, so the ACP case is the real one.
Nothing on the upstream path has a byte ceiling. The sharp edge is resume_blob, whose entire schema constraint is a minimum length — no maximum, and harness-authored. It is bounded only transitively and by accident: the blob arrives as a session/update on the output side, so boundAcpOutput errors the stream above 1 MiB and no larger blob is ever received. Nothing on the stdin path re-checks it, and base64 turns ≈1 MiB into ≈1.37 MiB inside one session/new frame. Its neighbours have no accidental ceiling at all: mcpServers is unbounded by server count, and builtinTools, continuity, and runtimeConfig are unbounded outright. input_buffer_full is therefore a condition your implementation must have a real answer for, not a corner case.

stdout is lossless only within a declared replay window

In-process, the readable stream is the child’s pipe. Between child and driver nothing is dropped, and no window is involved. Across a wire, resume after a dropped connection requires a bounded replay journal. A Runner disconnected longer than output_window_bytes cannot be served a correct suffix, and asking for a cursor below the journal’s low-water mark is refused as output_truncated. The design fails closed: output_truncated terminates the process rather than delivering a hole, because a gapped NDJSON stream cannot be resynchronised and a silent hole would corrupt the transcript. That is the right behavior and it is still a loss. Stated without softening:
A long enough disconnection kills a Run that would have survived in-process. The window is the tunable. It has not been sized against real outage data — no disconnect-duration instrumentation exists on the Runner↔control-plane connection yet — so today it would be guessed, not derived.
Downstream “backpressure” is this journal bound, not flow control. It is a fail-closed ceiling, not throttling.

evidence stops being an isolation cross-check

Restated here because it is the loss most likely to be forgotten. evidenceMatches is sixteen clauses. Nine bind evidence to state the Runner already holds — instance, provider and materialization revisions, root image, platform, profile digest, network mode, resource limits — and those survive a wire intact and unweakened, because the reference side is Runner-owned. A remote provider that starts a process on another image or under another network mode is caught exactly as it is today. Six more are internal consistency of the evidence object and were never cross-party. One clause is genuinely cross-party, and it does not survive: the comparison of evidence.enforcement against capabilities.enforcement. See the enforcement ceiling gap. On the wire seam, evidenceMatches is an identity and self-consistency check. It is not, and cannot be, an isolation check.

What is not lost

Worth stating, because it bounds the anxiety:
  • Cross-channel interleaving. stdout and stderr have no ordering guarantee relative to each other today either — the in-process shape is two independent pipes. A wire loses nothing that exists.
  • Chunk boundaries. Nothing observes them. ACP reframes on newlines; the one-shot driver concatenates to EOF. Re-chunk freely.
  • Multiplexing. At most one live process per instance. The Docker adapter reserves it today and the wire design inherits the rule, so there is no multiplexing to build — though the reservation is yours to keep, not the runtime’s.
  • The stream identity check. A transport shim constructs the three Web Streams itself, so the check passes by construction. It is a requirement to satisfy, not a thing to transport.
  • stderr fidelity. It is never a semantic channel — piped to the Runner’s own stderr under a debug flag, or discarded. It needs a bound and best-effort delivery, not exactly-once.
  • Exactly-once stdout across a mid-process drop. Enforced by the reader’s sequence filter, so a provider that lazily replays its whole journal on reconnect is still correct. Proved by the spike, including a drop injected after frames had actually been applied.

What is not yet proven

The openProcess wire was spiked end to end and every case passed, five consecutive runs. The spike’s green output is narrower than it reads, and these are the gaps:

Summary: what to treat as settled

Settled and safe to build against: the grading rule and its total order; the five facts and which three you cannot self-attest; the admission comparison and where it fails. Two of the three wire losses fail closed and announce themselvesinput_buffer_full is typed and retryable, output_truncated terminates the process rather than serving a gap. The third does not. The evidence cross-check does not fail when it degrades; it keeps passing and simply means less, because both sides of the comparison end up authored by the same partner. Nothing in the system currently records that difference, which is exactly why the enforcement ceiling is called blocking rather than pending. Not settled: the enforcement ceiling (blocking), the egress-grade ceiling on RunnerProviderCapability (blocking), the out_end/err_end and window frames, the sizing of output_window_bytes, and everything in the readiness table.

Next steps

  • Sandbox providers — the concept page and the publication readiness table.
  • Sandbox provider contract — the operations, the optional members, and the minimum provider.
  • Security — where a SandboxProfile’s network policy sits relative to a Connection’s egress rules, and why the latter is the stronger boundary.