Security model
How the Code Interpreter isolates untrusted code — hardened sandbox mode, Ed25519 JWT verification, signed execution manifests, network-egress control, environment scrubbing, and the secrets the stack auto-provisions.
The Code Interpreter runs untrusted, model-generated code, so its security model is layered: every request is authenticated, every job is cryptographically authorized, the sandbox holds no secrets, and outbound network access is brokered and logged. This page explains each layer.
The master switch: hardened sandbox mode
CODEAPI_HARDENED_SANDBOX_MODE (default true) enables the full security posture.
When on:
- The sandbox-runner scrubs forbidden environment variables before executing any job (see Environment scrubbing).
- Jobs require a signed execution manifest — unsigned requests are rejected.
- The sandbox has no direct network; only the egress-gateway is reachable, and only with a valid egress grant.
Set it the same everywhere
This flag must match on the api, service-worker, egress-gateway, and sandbox-runner. A mismatch causes jobs to be rejected (one side signs/scrubs, the other expects the opposite).
Request authentication (JWT)
The api is the only externally-reachable service, and it authenticates every request with an Ed25519 (EdDSA) JWT issued by the IntelliAsk app.
| Claim / setting | Variable | Default |
|---|---|---|
Issuer (iss) | CODEAPI_JWT_ISSUER | intelliask |
Audience (aud) | CODEAPI_JWT_AUDIENCE | codeapi |
| Allowed algorithms | CODEAPI_JWT_ALLOWED_ALGS | EdDSA,RS256 |
| Key ID hint | CODEAPI_JWT_KID | intelliask-codeapi |
| Verification key | CODEAPI_JWT_PUBLIC_KEY | (auto-provisioned) |
The app signs with the private half of the keypair; the api verifies with
CODEAPI_JWT_PUBLIC_KEY. Setting CODEAPI_AUTH_PROVIDER=none (or LOCAL_MODE=true)
disables this — development only.
Job authorization (signed execution manifests)
Passing the api's JWT check is not enough to run code. The service-worker signs
an execution manifest for each job with its Ed25519 private key
(CODEAPI_EXECUTION_MANIFEST_PRIVATE_KEY), and the sandbox-runner verifies it
with the matching public key (SANDBOX_EXECUTION_MANIFEST_PUBLIC_KEY) before
executing. This ensures a job reaching the sandbox genuinely came from the worker
and wasn't tampered with.
SANDBOX_REQUIRE_EGRESS_MANIFEST=true enforces that no unsigned job runs.
Environment scrubbing
Before running untrusted code, the sandbox-runner strips sensitive environment variables from the job's environment so leaked code can't read them. In hardened mode it removes anything matching these patterns:
| Pattern | Examples |
|---|---|
CODEAPI_* | CODEAPI_INTERNAL_SERVICE_TOKEN, CODEAPI_JWT_PUBLIC_KEY |
REDIS_* | REDIS_PASSWORD |
AWS_*, S3_*, MINIO_* | MINIO_SECRET_KEY, AWS_SECRET_ACCESS_KEY |
*SECRET*, *TOKEN*, *PASSWORD*, *PRIVATE_KEY* | any secret-shaped variable |
This is why the sandbox-runner itself holds no long-lived secrets it doesn't strictly need — the credentials live in the unprivileged services.
Network egress control
The sandbox is network-isolated (SANDBOX_DISABLE_NETWORKING=true). Its only
route out is the egress-gateway, reachable on the single allowed local port
(SANDBOX_ALLOWED_LOCAL_NETWORK_PORT=3190).
- The egress-gateway signs and verifies egress grants with
CODEAPI_EGRESS_GRANT_SECRET(HMAC). WithCODEAPI_EGRESS_LEDGER_REQUIRED=true, every proxied request must carry a valid grant. - Payloads are capped by
EGRESS_GATEWAY_MAX_TOOL_CALL_BYTES(1 MiB default). - File I/O and tool calls are routed to the file-server and tool-call-server through the gateway, so the sandbox never talks to them directly.
Service-to-service authentication
Internal calls between the codeapi services are authenticated with a shared HMAC
token, CODEAPI_INTERNAL_SERVICE_TOKEN (identical across all services). This
prevents a foothold in one service from freely impersonating another.
Tenancy
The Code Interpreter supports single- or multi-tenant operation:
| Variable | Purpose | Default |
|---|---|---|
CODEAPI_JWT_SINGLE_TENANT_ID | Tenant all jobs run under in single-tenant mode | legacy |
CODEAPI_TENANT_ISOLATION_STRICT | Reject requests without an explicit X-CodeAPI-Tenant header | false |
The Compose stack runs single-tenant by default.
The auto-provisioned secrets
None of the following should be set by hand — intelliask secrets gen and the
Garage bootstrap create them:
| Secret | Used by | Purpose |
|---|---|---|
CODEAPI_JWT_PUBLIC_KEY | api | Verify app-issued request JWTs |
CODEAPI_EXECUTION_MANIFEST_PRIVATE_KEY | service-worker | Sign execution manifests |
SANDBOX_EXECUTION_MANIFEST_PUBLIC_KEY | sandbox-runner | Verify execution manifests |
CODEAPI_INTERNAL_SERVICE_TOKEN | all services | Service-to-service HMAC auth |
CODEAPI_EGRESS_GRANT_SECRET | egress-gateway | Sign/verify egress grants |
GARAGE_RPC_SECRET, GARAGE_ADMIN_TOKEN | Garage | Cluster + admin auth |
MINIO_ACCESS_KEY, MINIO_SECRET_KEY | file-server, Garage | S3 credentials |
To rotate these, use intelliask secrets rotate and re-run the Garage bootstrap
where S3 keys change, then recreate the codeapi services with intelliask up.
Last updated on