Skip to main content
Internet connectivity is available in every sandbox, and external access is provided through a public URL.

Toggling internet access

When creating a sandbox, you can use the allowInternetAccess / allow_internet_access parameter to configure internet connectivity. Internet access is turned on by default, but it can be disabled for workloads with stricter security requirements.
import { Sandbox } from 'novita-sandbox/code-interpreter'

// Create sandbox with internet access enabled (default)
const sandbox = await Sandbox.create({ allowInternetAccess: true })

// Create sandbox without internet access
const isolatedSandbox = await Sandbox.create({ allowInternetAccess: false })
If internet access is disabled, the sandbox is prevented from initiating outbound network requests. This helps add an extra layer of protection when running sensitive code.
Passing a falsy value to allowInternetAccess / allow_internet_access has the same effect as adding ['0.0.0.0/0'] to network.denyOut / network.deny_out, which blocks every destination.

Fine-grained network control

Network configuration provides finer-grained control over outbound traffic by allowing you to define allowlists and denylists.

Allow and deny lists

IP addresses, CIDR blocks, or domain names that the sandbox is allowed to access can be specified.
import { Sandbox } from 'novita-sandbox/code-interpreter'

// Deny all traffic except specific IPs
const sandbox = await Sandbox.create({
  network: {
    denyOut: ['0.0.0.0/0'],
    allowOut: ['1.1.1.1', '8.8.8.0/24']
  }
})

// Deny specific IPs only
const restrictedSandbox = await Sandbox.create({
  network: {
    denyOut: ['8.8.8.8']
  }
})
The CIDR '0.0.0.0/0' / "0.0.0.0/0" is shorthand for “every destination”. An exported ALL_TRAFFIC constant resolves to the same 0.0.0.0/0 value if you prefer a named alternative to the literal.

Domain-based filtering

You can specify hostnames in allowOut / allow_out to permit outbound traffic to selected domains. When domain-based filtering is enabled, all remaining traffic must be blocked through denyOut / deny_out. Domain entries are only supported in allow lists and cannot be used in deny lists.
import { Sandbox } from 'novita-sandbox/code-interpreter'

// Allow only traffic to google.com
const sandbox = await Sandbox.create({
  network: {
    allowOut: ['google.com'],
    denyOut: ['0.0.0.0/0']
  }
})
Whenever a domain appears in the configuration, the default nameserver 8.8.8.8 is allowed automatically so that DNS resolution keeps working.
You can also match every subdomain of a domain with a wildcard:
import { Sandbox } from 'novita-sandbox/code-interpreter'

// Allow traffic to any subdomain of mydomain.com
const sandbox = await Sandbox.create({
  network: {
    allowOut: ['*.mydomain.com'],
    denyOut: ['0.0.0.0/0']
  }
})
Domains, IP addresses, and CIDR ranges can all be mixed together in the same list:
import { Sandbox } from 'novita-sandbox/code-interpreter'

// Allow traffic to specific domains and IPs
const sandbox = await Sandbox.create({
  network: {
    allowOut: ['api.example.com', '*.github.com', '8.8.8.8'],
    denyOut: ['0.0.0.0/0']
  }
})
Filtering by domain applies only to HTTP over port 80 (inspected via the Host header) and TLS over port 443 (inspected via SNI). Any other port falls back to CIDR-based matching, and UDP protocols such as QUIC/HTTP3 cannot be filtered by domain.

How blocked TCP connections behave

Because of the firewall architecture, a blocked outbound connection can still look successful from within the sandbox. The firewall must first accept the TCP connection before it can evaluate whether the target destination is permitted. As a result, code running inside the sandbox may see the connection succeed and the socket open, even if the destination is blocked. In that case, no traffic is actually delivered to the remote endpoint. To confirm that the destination is reachable, validate an application-level response instead of relying only on TCP connection success. For example, check for an HTTP status code, a completed TLS handshake, or the expected protocol response bytes. This behavior is a current limitation of how sandbox outbound traffic is routed through our firewall and may be updated in the future.

Priority rules

If both allow and deny rules are configured, the allow rules take priority. Therefore, any IP address that appears in both lists will still be permitted.
import { Sandbox } from 'novita-sandbox/code-interpreter'

// Even though all traffic is denied, 1.1.1.1 and 8.8.8.8 are explicitly allowed
const sandbox = await Sandbox.create({
  network: {
    denyOut: ['0.0.0.0/0'],
    allowOut: ['1.1.1.1', '8.8.8.8']
  }
})
The network settings take effect only when the sandbox is created — supply them to Sandbox.create. Once the sandbox exists, they are fixed and cannot be modified.

Sandbox public URL

Services in a sandbox can be accessed by using the sandbox’s public URL.
import { Sandbox } from 'novita-sandbox/code-interpreter'

const sandbox = await Sandbox.create()

// You need to always pass a port number to get the host
const host = sandbox.getHost(3000)
console.log(`https://${host}`)
The output will be like this:
https://3000-i62mff4ahtrdfdkyn2esc.sandbox.novita.ai
The leftmost segment of the hostname is exactly the port number you handed to the method.

Connecting to a server running inside the sandbox

You can connect to a server running inside the sandbox using the method described earlier; for example, start a lightweight HTTP server on port 3000 to serve files from its launch directory.
import { Sandbox } from 'novita-sandbox/code-interpreter'

const sandbox = await Sandbox.create()

// Start a simple HTTP server inside the sandbox.
const process = await sandbox.commands.run('python -m http.server 3000', { background: true })
const host = sandbox.getHost(3000)
const url = `https://${host}`
console.log('Server started at:', url)

// Fetch data from the server inside the sandbox.
const response = await fetch(url);
const data = await response.text();
console.log('Response from server inside sandbox:', data);

// Kill the server process inside the sandbox.
await process.kill()
This output will be as follows:
Server started at: https://3000-ip3nfrvajtqu5ktoxugc7.sandbox.novita.ai
Response from server inside sandbox: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href=".bash_logout">.bash_logout</a></li>
<li><a href=".bashrc">.bashrc</a></li>
<li><a href=".profile">.profile</a></li>
</ul>
<hr>
</body>
</html>

Masking request host headers

You can use the maskRequestHost / mask_request_host option to customize the Host header sent to services running inside the sandbox. This is useful when your application expects requests to follow a specific host format.
import { Sandbox } from 'novita-sandbox/code-interpreter'

// Create sandbox with custom host masking
const sandbox = await Sandbox.create({
  network: {
    maskRequestHost: 'localhost:${PORT}'
  }
})

// The ${PORT} variable will be replaced with the actual port number
// Requests to the sandbox will have Host header set to for example: localhost:8080
At request time, ${PORT} in the mask is substituted with the real port number of the service being addressed.
Last modified on June 4, 2026