back to microsandbox

features / network

the network is part of the boundary.

code you didn't write shouldn't decide where your packets go.

dithered network cables representing explicit sandbox egress policy

01

the default is safe, not open

by default, sandboxes can reach the public internet. private, host-local, link-local, and metadata destinations are blocked. egress can be reduced to an allowlist or disabled entirely. in the cloud, the non-public block cannot be lifted, even by you.

you do not configure anything to get this. it is the floor every sandbox starts on.

02

tighten it, or turn it off

reduce egress to an allowlist of the hosts a task actually needs, or disable it entirely for work that should never touch the network.

policy travels with the sandbox definition, so the same rules apply on your laptop and in the cloud.

credentials are destination-bound. the sandbox works with a placeholder; the real value is substituted host-side into supported intercepted outbound requests, only for destinations on your allow-list. an approved destination still receives the real credential and could reflect or misuse it, so scope your allow-lists accordingly.

03

in the cloud, the floor cannot be lifted

the non-public block is enforced host-side and cannot be turned off, even by you. a tenant workload cannot reach the private network, the metadata endpoint, or the host, no matter what its code tries.

how it works

how a packet is decided

01

the sandbox sends a request

code inside the guest tries to reach some destination.

02

the host classifies the destination

public internet, private range, host, link-local, or metadata endpoint.

03

the floor runs first

non-public destinations are denied before any tenant rule, and a permissive rule cannot shadow that decision.

04

your policy runs on what is left

public egress is allowed by default, or narrowed to your allowlist, or off.

see it work

remove the network interface

microsandbox 0.6.8
rust
use microsandbox::Sandbox;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let sandbox = Sandbox::builder("offline-job")
        .image("alpine")
        .disable_network()
        .replace()
        .create()
        .await?;

    let output = sandbox.shell("ip link").await?;
    println!("{}", output.stdout()?.trim());
    sandbox.stop().await?;
    Sandbox::remove("offline-job").await?;
    Ok(())
}

attach a domain policy

microsandbox 0.6.8
rust
use microsandbox::{NetworkPolicy, Sandbox};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let policy = NetworkPolicy::builder()
        .default_allow()
        .rule(|r| r.egress().deny().domain("blocked.example.com"))
        .rule(|r| r.egress().deny().domain_suffix(".evil.com"))
        .build()?;

    let sandbox = Sandbox::builder("filtered-job")
        .image("alpine")
        .network(|network| network.policy(policy))
        .replace()
        .create()
        .await?;

    sandbox.stop().await?;
    Sandbox::remove("filtered-job").await?;
    Ok(())
}

set the boundary beside the workload.