Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

reloaded-code-bubblewrap

Builds bubblewrap profiles, availability checks, and wrapped commands for reloaded-code.

Linux only. Two preset profiles: Public Bot (untrusted input, no network) and Trusted Maintenance (trusted automation, network enabled).

Documentation · API Reference

Main Types

  • Builder - Builds a bubblewrap profile.
  • Profile - A validated bubblewrap profile ready for reuse.
  • Availability::detect - Checks whether bwrap can run.
  • wrap::wrap_command - Builds a bwrap command from a profile.
  • tokio::build_command_wrap - Builds the async wrapped command.
  • blocking::build_command_wrap - Builds the blocking wrapped command.

Feature Flags

  • tokio: enables tokio::build_command_wrap.
  • blocking: enables blocking::build_command_wrap.

Usage

Building a Profile

use reloaded_code_bubblewrap::{
    Preset, Builder, TmpBacking,
};
use std::path::Path;

fn main() -> Result<(), reloaded_code_bubblewrap::LinuxBwrapError> {
let profile = Builder::public_bot(
    Path::new("/host/workspace"),         // workspace: host directory mounted into the sandbox
    Path::new("/tmp/sandbox-home"),       // synthetic_home: host dir mounted as $HOME (/home/sandbox) inside the sandbox
    Path::new("/tmp/sandbox-cache"),      // cache_root: host cache root used for sandbox cache/state dirs
    Some(TmpBacking::Tmpfs),              // tmp_backing: how sandbox /tmp is backed (RAM or host dir)
)
.build()?;

assert_eq!(profile.preset(), Some(Preset::PublicBot));
    Ok(())
}

Detecting Availability

use reloaded_code_bubblewrap::Availability;

match Availability::detect() {
    Availability::Available => {
        println!("sandbox is ready");
    }
    Availability::Unavailable { reason } => {
        eprintln!("sandbox unavailable: {reason}");
    }
    Availability::Unknown => {
        println!("availability not checked");
    }
}

Wrapping a Command

use reloaded_code_bubblewrap::{
    wrap, Preset, Builder, TmpBacking,
};
use std::path::Path;

fn main() -> Result<(), reloaded_code_bubblewrap::LinuxBwrapError> {
let profile = Builder::public_bot(
    Path::new("/host/workspace"),         // workspace: host directory mounted into the sandbox
    Path::new("/tmp/sandbox-home"),       // synthetic_home: host dir mounted as $HOME (/home/sandbox) inside the sandbox
    Path::new("/tmp/sandbox-cache"),      // cache_root: host cache root used for sandbox cache/state dirs
    Some(TmpBacking::Tmpfs),              // tmp_backing: how sandbox /tmp is backed (RAM or host dir)
)
.build()?;

let wrapped = wrap::wrap_command(
    &profile,                  // profile: validated profile from Builder::build()
    "echo hello",              // command: shell command string to execute
    None,                      // workdir: host working directory (None = use workspace)
).unwrap();
assert!(wrapped.program().ends_with("bwrap"));
    Ok(())
}

Running with Tokio

// tokio::build_command_wrap(&profile, command, workdir)
//   profile: validated Profile
//   command: shell command string to execute
//   workdir: host working directory (None = use workspace)

See tokio::build_command_wrap (requires tokio feature).

Running with Blocking

// blocking::build_command_wrap(&profile, command, workdir)
//   profile: validated Profile
//   command: shell command string to execute
//   workdir: host working directory (None = use workspace)

See blocking::build_command_wrap (requires blocking feature).

Presets

  • [Preset::PublicBot] - Safer defaults for untrusted input. Uses a synthetic home, a cleaned PATH, read-only system mounts, optional RAM-backed /tmp, and no network.
  • [Preset::TrustedMaintenance] - Broader defaults for trusted jobs. Uses a read-only host root, a cleaned PATH, writable overlays, host-backed /tmp, and keeps network on.

TrustedMaintenance is only for trusted jobs. A command can send out any data it can read.

Preset helpers return a builder, so you can still change paths, mounts, and env vars before calling .build(). That build step validates profile-owned inputs and precomputes the reusable bwrap argv prefix.

[TmpBacking::Tmpfs] keeps sandbox /tmp in memory. Use [TmpBacking::BindHost] to mount a host directory at /tmp.

wrap::wrap_command tries a visible host bash first and falls back to sh. On Nix systems that is often under /nix/store/.... On FHS systems it is often under /usr/bin or /bin.

[Preset::PublicBot] filters out user-home, temp, wrapper, and per-user profile directories from the inherited PATH. [Preset::TrustedMaintenance] keeps more host PATH entries, but still drops entries under directories hidden by the profile.

For more details on sandbox profiles and trade-offs, see Extra Sandboxing Notes.

Builder Lists

Setters like with_read_only_mounts replace the whole list. They do not append. That keeps the builder state easy to read.

Errors

  • Missing bwrap is reported clearly.
  • Environments that cannot create a sandbox are reported clearly.
  • Invalid profile-owned paths and invalid credential mounts are rejected at build time.
  • Invalid per-command working directories are rejected before spawn.

For the internal architecture and module layout, see ARCHITECTURE.md.