Back to Microsandbox

TLS interception

docs/networking/tls.mdx

0.6.95.5 KB
Original Source

<Tooltip tip="TLS interception and host CA trust are not available on Microsandbox Cloud."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

TLS interception lets Microsandbox inspect HTTPS traffic. This enables URL policy checks, request logging, and secure secret injection for matching hosts.

How it works

When interception is enabled, Microsandbox:

  1. Loads an interception certificate authority, or CA.
  2. Adds that CA to the guest's trust store.
  3. Creates a certificate for each intercepted host.
  4. Opens a separate verified TLS connection to the upstream server.

The default CA is stored at ~/.microsandbox/tls/ca.{crt,key} and reused by local sandboxes. Delete both files to generate a new CA. Use the intercept CA certificate and key settings when sandboxes should use a CA that you provide.

Enabling interception

<CodeGroup> ```rust Rust use microsandbox::Sandbox;

let sb = Sandbox::builder("worker") .image("python") .network(|n| n.tls(|t| t .bypass("pinned-api.example.com") .bypass("*.gov") )) .create() .await?;


```typescript TypeScript
import { Sandbox } from "microsandbox";

await using sb = await Sandbox.builder("worker")
  .image("python")
  .network((n) => n.tls((t) =>
    t.bypass("pinned-api.example.com").bypass("*.gov"),
  ))
  .create();
python
from microsandbox import Network, Sandbox, TlsConfig

sb = await Sandbox.create(
    "worker",
    image="python",
    network=Network(
        tls=TlsConfig(bypass=("pinned-api.example.com", "*.gov")),
    ),
)
go
sb, err := m.CreateSandbox(ctx, "worker",
    m.WithImage("python"),
    m.WithNetwork(&m.NetworkConfig{
        TLS: &m.TLSConfig{
            Bypass: []string{"pinned-api.example.com", "*.gov"},
        },
    }),
)
bash
msb create python --name worker \
  --tls-intercept \
  --tls-bypass "pinned-api.example.com" \
  --tls-bypass "*.gov"
</CodeGroup>

Bypass patterns

Some clients trust a specific certificate or public key instead of the guest's trust store. Interception will fail for these clients.

Add their hosts to the bypass list. Exact domains such as api.example.com and wildcards such as *.apple.com are supported. Bypassed traffic stays encrypted between the guest and upstream server, so content-based policy checks and secret injection do not apply.

Upstream CA trust

The proxy verifies upstream certificates with the host's root store by default. You can add:

  • a CA trusted for every intercepted host
  • a CA trusted only for matching hosts
  • a host pattern that skips upstream verification
<CodeGroup> ```rust Rust let sb = Sandbox::builder("agent") .image("python") .network(|n| n.tls(|t| t .upstream_ca_cert("/etc/ssl/corp-root.pem") .upstream_ca_cert_for("api.internal.example.com", "./certs/api-ca.pem") .verify_upstream_for("*.preview.internal", false) )) .create() .await?; ```
bash
msb create python --name agent \
  --tls-intercept \
  --tls-upstream-ca-cert /etc/ssl/corp-root.pem \
  --tls-upstream-ca-cert-for 'api.internal.example.com=./certs/api-ca.pem' \
  --tls-no-verify-upstream-for '*.preview.internal'
</CodeGroup>

Skipping verification is similar to using curl -k. Use it only for hosts you control and only when a trusted CA is not available.

Limits

  • Clients that pin certificates or public keys must be bypassed.
  • Bypassed traffic cannot use content-based policy checks or secret injection.
  • Guest client certificates are not proxied. Bypass hosts that require guest mTLS.
  • QUIC and HTTP/3 traffic are not intercepted.

Trusting host CAs

Corporate proxies often replace server certificates with certificates signed by a company CA. The host trusts that CA, but a sandbox normally does not. Commands such as apk update, pip install, and curl can then fail with a certificate error.

Enable host CA trust to copy trusted host roots into the guest when it starts:

<CodeGroup> ```rust Rust let sb = Sandbox::builder("devbox") .image("alpine") .network(|n| n.trust_host_cas(true)) .create() .await?; ```
typescript
await using sb = await Sandbox.builder("devbox")
  .image("alpine")
  .network((n) => n.trustHostCAs(true))
  .create();
python
sb = await Sandbox.create(
    "devbox",
    image="alpine",
    network=Network(trust_host_cas=True),
)
go
trustHostCAs := true
sb, err := m.CreateSandbox(ctx, "devbox",
    m.WithImage("alpine"),
    m.WithNetwork(&m.NetworkConfig{
        TrustHostCAs: &trustHostCAs,
    }),
)
bash
msb run alpine --trust-host-cas -- apk update
</CodeGroup> <Note> Host CA trust gives the guest every root certificate trusted by the host. Enable it only when you trust the host's CA store. </Note>

Interaction with TLS interception

TLS interception covers configured ports, with port 443 enabled by default. TLS interception and host CA trust solve different problems:

FeatureCovers
TLS interceptionConfigured TLS ports and hosts that are not bypassed
Host CA trustAny guest connection that uses the guest's system trust store

Use both when you need HTTPS inspection and also need raw TLS connections to trust corporate certificates. Raw TLS includes bypassed hosts, custom TLS ports, and protocols such as Postgres or Redis over TLS.

See also