Untrusted code never touches your kernel
Every preview, test run, validation job, delegated inner-runner session, and self-repair candidate executes inside gVisor (runsc), a userspace kernel between anything CrewWork runs on your behalf and the host. Container creation fails closed if the pinned runtime is unavailable, so untrusted work never falls back to the host’s ordinary runtime.
- gVisor (runsc)
- Kernel-boundary sandboxing
- Fail-closed by default
- Checksum-verified
- preview
- runsc
- test run
- runsc
- validation job
- runsc
- agent session
- runsc
- self-repair
- runsc
- release build
- gVisor BuildKit
What gVisor isolation actually means
A container under runsc still looks ordinary from the outside, but a full kernel-boundary sandbox now sits between anything inside it and the real operating system underneath.
CrewWork pins gVisor release-20260727.0, checksum-verified separately for x86_64 and arm64, installed by a host installer script that registers runsc as an additional Docker runtime rather than replacing Docker’s default. Trusted platform services and GPU-backed containers are unaffected and keep running on the host kernel.
Only the containers that touch untrusted, generated, or candidate code opt into gVisor.
From preview to release, a hard ceiling for every container class
Every place CrewWork executes code it did not write, or generated code that has not yet earned your trust, runs behind the same kernel boundary. CPU, memory, and process-count limits set the blast radius inside it, enforced by Docker’s own cgroup limits on top of gVisor.
| Container class | Caps | Notes |
|---|---|---|
| Delegated inner-runner sessions | 2 CPUs · 4 GB · 1,024 processes | This ceiling is fixed rather than a tunable default. Every session container for the delegated inner-runner execution backend launches with runtime="runsc" and this exact cap. |
| Infinite Coder command execution and test-run executor | 2 CPUs · 2 GB · 1,024 processes (default) | Both share this default. The delivery-run process ceiling is configurable per deployment, with a floor of 16, so a runaway fork storm still gets stopped even at the smallest setting. |
| Job runner (matrix & validation jobs) | 2 CPUs · 2 GB · 512 processes (default) | Stages a workspace snapshot from the calling container, then runs unit, integration, static-analysis, and security checks inside its own sandbox. |
| Preview outer runner | 2 CPUs · 4 GB · 512 processes (default) | The privileged supervisor that hosts a private Docker daemon for the candidate app. It keeps the host cgroup namespace on purpose, so its pinned runsc can bound the inner sandbox; candidate code itself never leaves that inner sandbox. |
| Preview candidate app | 1.5 CPUs · 2 GB · 256 processes (default) | The generated application itself. Every Linux capability is dropped except the four needed to chown files, bind low ports, and drop privileges after startup. |
| DAST scanner (ZAP) | 1 CPU · 1,536 MB · 256 processes | Runs read-only as a non-root user, on an ephemeral network scoped to the exact preview app under test, then torn down. |
A preview is not just another container
A preview environment runs generated, unreviewed application code, and it typically exposes a public-facing port. That combination gets three layers of protection on top of the gVisor boundary itself, so a compromised or malicious preview cannot reach the rest of your CrewWork deployment.
- identity
- each preview-runner container carries an HMAC-SHA256 signature over its project, container name, instance ID, created-at, and expiry, verified before the orchestrator will trust or reuse it. An ambiguous or duplicate identity hard-fails instead of guessing the newest running container.
- network
- the inner Docker daemon’s bridge network is pinned to an address pool that never overlaps CrewWork’s own service networks, so a preview cannot reach platform infrastructure by coincidence.
- egress
- the runner entrypoint installs iptables and ip6tables DOCKER-USER DROP rules naming the protected internal ranges, so a preview container is actively refused if it tries to reach them, not merely absent from a routing table.
Test execution is verified network-isolated
Test-run containers get no Docker socket and no mounted volumes.
- install dependencies on a network-enabled bridge, against an allowlisted package index
- disconnect the container leaves every network
- verify the disconnection is verified before your test command runs
- stop if verification fails, the run raises network_isolation_failed and stops
See Testing & Quality Gates for the full 10-language test engine this protects.
The build pipeline is sandboxed too
Release and candidate OCI image builds run through a custom buildkit-runsc image, a version-pinned BuildKit and containerd bundled with the same runsc binary used everywhere else, so every RUN step in a Dockerfile executes inside the same gVisor boundary as runtime workloads. The guarantee covers how release images are built, not only how they run.
Isolation is layered, not singular
Kernel-boundary sandboxing is the foundation. Two more layers close off attack classes that sandboxing alone does not address.
- Hardened XML parsing
- Untrusted XML, including scanner report output and indexed project content, passes through a single hardened boundary built on defusedxml, with DTDs, external entities, and entity expansion all forbidden. Malformed or unsafe XML raises a typed error instead of silently resolving an external entity, closing off the classic XXE attack class.
- Own TLS ingress
- The production stack ships its own Nginx ingress as the single route and header authority. It terminates TLS 1.2 and TLS 1.3 with HSTS enabled, and unrecognized hosts fail closed to an HTTP-to-HTTPS redirect.
These sit alongside the rest of the platform’s security posture: fail-closed write scope, encrypted secrets, and prompt-injection neutralization. See Security for the complete model.
See whether CrewWork fits your work.
CrewWork is built and running, and not yet generally available.
- worth discussing
- The errors and backlog you would hand off
- Where your source has to stay
- The evidence you would need to trust a change