Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,10 @@ Use default runtime discovery only for trusted applications. The bounded host
subprocess currently requires POSIX; on other platforms use `--secure-ast` for
execution-free discovery or `--vm` for the hardened untrusted-code boundary.

`--vm` requires a prebuilt immutable image digest and a configured gVisor/Kata
runtime. It never builds an image or imports application code on the host; see
the [runtime sandbox policy](docs/runtime-sandbox.md).
`--vm` requires a prebuilt immutable image digest, dependency/snapshot/SBOM
attestations, and a configured gVisor/Kata runtime. It never pulls or builds an
image or imports application code on the host; see the
[runtime sandbox policy](docs/runtime-sandbox.md).

`--scip` requires pinned external tools on `PATH`: `scip-query` 0.16.0,
`@sourcegraph/scip-python` 0.6.6, and SCIP CLI. Install Node tooling outside the
Expand Down
21 changes: 13 additions & 8 deletions benchmarks/results/runtime-sandbox-v1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,20 @@ execution. It deliberately publishes no secure-vs-runtime quality numbers.
The command builder and lifecycle tests attest:

- immutable repository-digest resolution with ambiguity rejection;
- mandatory dependency-lock and SBOM SHA-256 attestations;
- gVisor/Kata requirement (`runc` is rejected);
- no network, host environment inheritance, devices, privileges, capabilities,
sockets, or writable checkout/root;
- non-root execution, read-only non-recursive mounts, deny-by-default seccomp,
and bounded noexec tmpfs;
- mandatory dependency-lock, source-snapshot-lock, SBOM, and seccomp SHA-256
attestations;
- an explicit gVisor/Kata runtime allowlist (`runc` and unknown runtime names are
rejected);
- no image pull, network, host environment inheritance, IPC sharing, retained
logs, devices, privileges, capabilities, sockets, or writable checkout/root;
- non-root execution, Docker 29+ `bind-recursive=disabled` read-only mounts,
image `Config.Volumes` rejection, deny-by-default seccomp, and bounded noexec
tmpfs;
- memory/swap, CPU, PID, nofile, nproc, fsize, core, timeout, and output limits;
- unique name/CID cleanup with post-removal inspection;
- deterministic content-addressed policy provenance;
- unique name/CID cleanup with successful bounded absence queries;
- deterministic content-addressed policy provenance and rejection of mutated
policy bytes, mount-grammar metacharacters, broad/symlinked/unreadable mounts,
special files, and malformed CID values;
- malformed output and endpoint schema rejection.

The wheel build contains
Expand Down
33 changes: 24 additions & 9 deletions docs/runtime-sandbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,46 @@ Set the immutable image explicitly:
```bash
export FASTAPI_ENDPOINT_DETECTOR_VM_IMAGE='registry.example/detector@sha256:<64-hex>'
export FASTAPI_ENDPOINT_DETECTOR_VM_LOCK_SHA256='sha256:<64-hex>'
export FASTAPI_ENDPOINT_DETECTOR_VM_SNAPSHOT_SHA256='sha256:<64-hex>'
export FASTAPI_ENDPOINT_DETECTOR_VM_SBOM_SHA256='sha256:<64-hex>'
fastapi-endpoint-detector list --vm --app ./application
```

The image must already contain all snapshot-pinned dependencies. The CLI no
longer builds a mutable image automatically. A content-addressed dependency lock
and SBOM attestation are mandatory launch inputs. Their production remains a
release-pipeline responsibility; benchmark manifests record both hashes, the
image digest, and `VMExecutor.policy_provenance()`.
The image must already contain all snapshot-pinned dependencies, declare no
`Config.Volumes`, and is never pulled during a comparator launch. The CLI no
longer builds a mutable image automatically. Content-addressed dependency-lock,
source-snapshot-lock, and SBOM attestations are mandatory launch inputs. Their
production remains a
release-pipeline responsibility; benchmark manifests record all three hashes,
the image digest, and `VMExecutor.policy_provenance()`. The packaged seccomp
profile has a pinned digest in the executor; a custom profile requires
`FASTAPI_ENDPOINT_DETECTOR_VM_SECCOMP_SHA256` and must match it exactly.

## Policy v1

Docker Engine and CLI 29.0 or newer (API 1.52+) are the documented minimum.
Bind mounts use Docker 29's `bind-recursive=disabled`; the removed
`bind-nonrecursive` spelling is intentionally not emitted.

Every launch uses argv without a shell and enforces:

- gVisor/Kata runtime rather than the default OCI runtime;
- no network, devices, host sockets, privileges, or added capabilities;
- an explicit allowlist of gVisor/Kata runtime names rather than arbitrary or
default OCI runtimes;
- no daemon image pull, network, IPC sharing, retained container logs, devices,
host sockets, privileges, or added capabilities;
- non-root UID/GID `65532:65532` and `no-new-privileges`;
- a read-only root and exact, read-only, non-recursive app/diff mounts;
- a read-only root and exact, read-only, non-recursive app/diff mounts; mount
grammar metacharacters, symlinked or unreadable trees, special files,
filesystem-root, home-root, and other broad system mounts fail before Docker
starts;
- a 64 MiB `noexec,nosuid,nodev` tmpfs;
- memory=swap, CPU, PID, `nofile`, `nproc`, `fsize`, core, timeout, and combined
stdout/stderr limits;
- a clean explicit process environment;
- the versioned deny-by-default seccomp profile at
`executor/policies/runtime-seccomp-v1.json`;
- a unique container name plus CID file, followed by kill and forced removal on
- a unique container name plus CID file, followed by kill, forced removal, and
successful bounded inventory queries proving both identifiers absent on
success, failure, timeout, or output overflow.

The policy and seccomp bytes are content-addressed in provenance. Missing
Expand Down
Loading
Loading