Skip to content
LogoLogo

Egress

Sandboxes are open by default. A sandbox with no egress rules can reach external hosts. For sandboxes that run untrusted or AI-generated code, set an allowlist before the sandbox runs any user-supplied input. CreateOS enforces the policy outside the sandbox.

Egress rules control which external hosts a sandbox can reach. There is one default and it is worth stating plainly: an empty rule list means open egress: all outbound traffic is allowed. A non-empty rule list means deny-by-default: only the listed destinations pass; everything else is dropped in-kernel on the host, outside the VM, so code inside the sandbox cannot rewrite or route around the policy. Inbound is closed regardless (see ingress_enabled). Pass egress at create time so the allowlist is in force before the first command runs; the same rules can be changed live afterwards.

A deny-by-default Python job, for example, needs exactly two rules: ["pypi.org:443", "*.pythonhosted.org:443"]. Rules cover any port and any protocol to the listed host, IP or CIDR; host:port narrows to one port. Both IPv4 addresses and hostnames (with *. wildcards) are accepted, so there is no separate "domain allowlist" mode with its own restrictions.

Rules apply live with no sandbox restart required.

Get your API key from https://createos.sh/app/profile. Pass it as X-Api-Key: <token> on every request.

Base URL: https://api.sb.createos.sh


At a glance

  • Base URL: https://api.sb.createos.sh
  • Auth: X-Api-Key: <token> header. Get a token
  • Response envelope: JSend, {"status": "...", "data": ...}

Rule formats

Each rule is a string in one of these forms:

FormatExampleEffect
hostpypi.orgAllow HTTP and HTTPS to that hostname on TCP ports 80 and 443.
host:portgithub.com:443Restrict a hostname rule to TCP 80 or 443. Use an IP/CIDR rule for other ports.
*.host*.pythonhosted.orgWildcard subdomain match.
ip1.1.1.1Allow all ports to that IP.
ip:port1.1.1.1:53Allow only that port.
cidr10.0.0.0/8Allow all ports to that CIDR block.
cidr:port10.0.0.0/8:8080Allow only that port in the block.
**Allow all destinations (same as empty list).

Empty list / null / ["*"] allows outbound traffic without a destination allowlist.

There is no denylist token. To block one destination you must list all destinations you do want.

GET /v1/sandboxes/{id}/egress

Read the current egress allowlist for a sandbox.

Auth required: Yes

Path parameters

ParameterDescription
idSandbox id.

Example

curl https://api.sb.createos.sh/v1/sandboxes/sb-01K.../egress \
  -H "X-Api-Key: $CREATEOS_API_KEY"

Success response 200

{
  "status": "success",
  "data": {
    "id": "sb-01K…",
    "egress": ["pypi.org", "*.pythonhosted.org", "github.com:443"]
  }
}

Notable errors: 404 sandbox not found or not owned by caller.

PUT /v1/sandboxes/{id}/egress

Replace the egress allowlist without restarting the sandbox. Allow time for hostname policy updates to propagate before running a workload that depends on the new rules.

Auth required: Yes

Path parameters

ParameterDescription
idSandbox id.

Request body

FieldTypeRequiredDescription
egressarray of stringsNoFull replacement allowlist. null, missing, [], or ["*"] all mean allow-all.

Example: restrict to PyPI and GitHub

curl -X PUT https://api.sb.createos.sh/v1/sandboxes/sb-01K.../egress \
  -H "X-Api-Key: $CREATEOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "egress": [
      "pypi.org",
      "*.pythonhosted.org",
      "github.com:443",
      "1.1.1.1:53"
    ]
  }'

Success response 200

{
  "status": "success",
  "data": {
    "id": "sb-01K…",
    "egress": ["pypi.org", "*.pythonhosted.org", "github.com:443", "1.1.1.1:53"]
  }
}

Example: restore allow-all

curl -X PUT https://api.sb.createos.sh/v1/sandboxes/sb-01K.../egress \
  -H "X-Api-Key: $CREATEOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"egress": []}'

Notable errors: 404 sandbox not found.

Setting egress at sandbox creation

You can also supply the initial egress list when creating a sandbox. Pass egress in the POST /v1/sandboxes body:

{
  "shape": "s-1vcpu-256mb",
  "egress": ["pypi.org", "github.com:443"]
}

See /Sandbox/REST-API/Sandboxes for the full create request shape.