Skip to main content

Crate bashkit

Crate bashkit 

Source
Expand description

BashKit - Sandboxed bash interpreter for multi-tenant environments

Sandboxed bash interpreter for AI agents, CI/CD pipelines, and code sandboxes. Written in Rust.

§Features

  • POSIX compliant - Substantial IEEE 1003.1-2024 Shell Command Language compliance
  • Sandboxed execution - No real filesystem access by default
  • Virtual filesystem - InMemoryFs, OverlayFs, MountableFs
  • Resource limits - Command count, loop iterations, function depth
  • Network allowlist - Control HTTP access per-domain
  • Custom builtins - Extend with domain-specific commands
  • Async-first - Built on tokio

§Built-in Commands (66)

CategoryCommands
Coreecho, printf, cat, read
Navigationcd, pwd, ls, find
Flow controltrue, false, exit, return, break, continue, test, [
Variablesexport, set, unset, local, shift, source, .
Text processinggrep, sed, awk, jq, head, tail, sort, uniq, cut, tr, wc
File operationsmkdir, rm, cp, mv, touch, chmod, rmdir
File inspectionfile, stat, less
Archivestar, gzip, gunzip
Utilitiessleep, date, basename, dirname, timeout, wait, xargs, tee
System infowhoami, hostname, uname, id, env, printenv, history
Networkcurl, wget (requires NetworkAllowlist)

§Shell Features

  • Variables and parameter expansion ($VAR, ${VAR:-default}, ${#VAR})

  • Command substitution ($(cmd))

  • Arithmetic expansion ($((1 + 2)))

  • Pipelines and redirections (|, >, >>, <, <<<, 2>&1)

  • Control flow (if/elif/else, for, while, case)

  • Functions (POSIX and bash-style)

  • Arrays (arr=(a b c), ${arr[@]}, ${#arr[@]})

  • Glob expansion (*, ?)

  • Here documents (<<EOF)

  • compatibility_scorecard - Full compatibility status

§Quick Start

use bashkit::Bash;

let mut bash = Bash::new();
let result = bash.exec("echo 'Hello, World!'").await?;
assert_eq!(result.stdout, "Hello, World!\n");
assert_eq!(result.exit_code, 0);

§Basic Usage

§Simple Commands

use bashkit::Bash;

let mut bash = Bash::new();

// Echo with variables
let result = bash.exec("NAME=World; echo \"Hello, $NAME!\"").await?;
assert_eq!(result.stdout, "Hello, World!\n");

// Pipelines
let result = bash.exec("echo -e 'apple\\nbanana\\ncherry' | grep a").await?;
assert_eq!(result.stdout, "apple\nbanana\n");

// Arithmetic
let result = bash.exec("echo $((2 + 2 * 3))").await?;
assert_eq!(result.stdout, "8\n");

§Control Flow

use bashkit::Bash;

let mut bash = Bash::new();

// For loops
let result = bash.exec("for i in 1 2 3; do echo $i; done").await?;
assert_eq!(result.stdout, "1\n2\n3\n");

// If statements
let result = bash.exec("if [ 5 -gt 3 ]; then echo bigger; fi").await?;
assert_eq!(result.stdout, "bigger\n");

// Functions
let result = bash.exec("greet() { echo \"Hello, $1!\"; }; greet World").await?;
assert_eq!(result.stdout, "Hello, World!\n");

§File Operations

All file operations happen in the virtual filesystem:

use bashkit::Bash;

let mut bash = Bash::new();

// Create and read files
bash.exec("echo 'Hello' > /tmp/test.txt").await?;
bash.exec("echo 'World' >> /tmp/test.txt").await?;

let result = bash.exec("cat /tmp/test.txt").await?;
assert_eq!(result.stdout, "Hello\nWorld\n");

// Directory operations
bash.exec("mkdir -p /data/nested/dir").await?;
bash.exec("echo 'content' > /data/nested/dir/file.txt").await?;

§Configuration with Builder

Use Bash::builder() for advanced configuration:

use bashkit::{Bash, ExecutionLimits};

let mut bash = Bash::builder()
    .env("API_KEY", "secret123")
    .username("deploy")
    .hostname("prod-server")
    .limits(ExecutionLimits::new().max_commands(100))
    .build();

let result = bash.exec("whoami && hostname").await?;
assert_eq!(result.stdout, "deploy\nprod-server\n");

§Custom Builtins

Register custom commands to extend BashKit with domain-specific functionality:

use bashkit::{Bash, Builtin, BuiltinContext, ExecResult, async_trait};

struct Greet;

#[async_trait]
impl Builtin for Greet {
    async fn execute(&self, ctx: BuiltinContext<'_>) -> bashkit::Result<ExecResult> {
        let name = ctx.args.first().map(|s| s.as_str()).unwrap_or("World");
        Ok(ExecResult::ok(format!("Hello, {}!\n", name)))
    }
}

let mut bash = Bash::builder()
    .builtin("greet", Box::new(Greet))
    .build();

let result = bash.exec("greet Alice").await?;
assert_eq!(result.stdout, "Hello, Alice!\n");

Custom builtins have access to:

  • Command arguments (ctx.args)
  • Environment variables (ctx.env)
  • Shell variables (ctx.variables)
  • Virtual filesystem (ctx.fs)
  • Pipeline stdin (ctx.stdin)

See BashBuilder::builtin for more details.

§Virtual Filesystem

BashKit provides three filesystem implementations:

  • InMemoryFs: Simple in-memory filesystem (default)
  • OverlayFs: Copy-on-write overlay for layered storage
  • MountableFs: Mount multiple filesystems at different paths

See the fs module documentation for details and examples.

§Direct Filesystem Access

Access the filesystem directly via Bash::fs():

use bashkit::{Bash, FileSystem};
use std::path::Path;

let mut bash = Bash::new();
let fs = bash.fs();

// Pre-populate files before running scripts
fs.mkdir(Path::new("/config"), false).await?;
fs.write_file(Path::new("/config/app.conf"), b"debug=true").await?;

// Run a script that reads the config
let result = bash.exec("cat /config/app.conf").await?;
assert_eq!(result.stdout, "debug=true");

// Read script output directly
bash.exec("echo 'result' > /output.txt").await?;
let output = fs.read_file(Path::new("/output.txt")).await?;
assert_eq!(output, b"result\n");

§HTTP Access (curl/wget)

Enable the http_client feature and configure an allowlist for network access:

use bashkit::{Bash, NetworkAllowlist};

let mut bash = Bash::builder()
    .network(NetworkAllowlist::new()
        .allow("https://httpbin.org"))
    .build();

// curl and wget now work for allowed URLs
let result = bash.exec("curl -s https://httpbin.org/get").await?;
assert!(result.stdout.contains("httpbin.org"));

Security features:

  • URL allowlist enforcement (no access without explicit configuration)
  • 10MB response size limit (prevents memory exhaustion)
  • 30 second timeout (prevents hanging)
  • No automatic redirects (prevents allowlist bypass)
  • Zip bomb protection for compressed responses

See NetworkAllowlist for allowlist configuration options.

§Examples

See the examples/ directory for complete working examples:

  • basic.rs - Getting started with BashKit
  • custom_fs.rs - Using different filesystem implementations
  • custom_filesystem_impl.rs - Implementing the FileSystem trait
  • resource_limits.rs - Setting execution limits
  • sandbox_identity.rs - Customizing username/hostname
  • text_processing.rs - Using grep, sed, awk, and jq
  • agent_tool.rs - LLM agent integration

§Guides

§Resources

§Ecosystem

BashKit is part of the Everruns ecosystem.

Re-exports§

pub use tool::BashTool;
pub use tool::BashToolBuilder;
pub use tool::Tool;
pub use tool::ToolRequest;
pub use tool::ToolResponse;
pub use tool::ToolStatus;
pub use tool::VERSION;

Modules§

compatibility_scorecard
Bash compatibility scorecard.
custom_builtins_guide
Guide for creating custom builtins to extend BashKit.
parser
Parser module - exposed for fuzzing and testing Parser module for BashKit
threat_model
Security threat model guide.
tool
Tool contract for LLM integration Tool trait and BashTool implementation

Structs§

Bash
Main entry point for BashKit.
BashBuilder
BuiltinContext
Execution context for builtin commands.
DirEntry
An entry in a directory listing.
ExecResult
Result of executing a bash script.
ExecutionCounters
Execution counters for tracking resource usage
ExecutionLimits
Resource limits for script execution
FsLimits
Filesystem resource limits.
FsUsage
Current filesystem usage statistics.
InMemoryFs
In-memory filesystem implementation.
Metadata
File or directory metadata.
MountableFs
Filesystem with Unix-style mount points.
NetworkAllowlist
Network allowlist configuration for controlling HTTP access.
OverlayFs
Copy-on-write overlay filesystem.

Enums§

ControlFlow
Control flow signals from commands like break, continue, return
Error
BashKit error types.
FileType
Type of a filesystem entry.
FsLimitExceeded
Error returned when a filesystem limit is exceeded.
LimitExceeded
Error returned when a resource limit is exceeded

Traits§

Builtin
Trait for implementing builtin commands.
FileSystem
Async virtual filesystem trait.

Type Aliases§

Result
Result type alias using BashKit’s Error.

Attribute Macros§

async_trait