Skip to main content

rust_bash/
lib.rs

1//! A sandboxed bash interpreter with a virtual filesystem.
2//!
3//! `rust-bash` executes bash scripts safely in-process — no containers, no VMs,
4//! no host access. All file operations happen on a pluggable virtual filesystem
5//! (in-memory by default), and configurable execution limits prevent runaway scripts.
6//!
7//! # Quick start
8//!
9//! ```rust
10//! use rust_bash::RustBashBuilder;
11//! use std::collections::HashMap;
12//!
13//! let mut shell = RustBashBuilder::new()
14//!     .files(HashMap::from([
15//!         ("/hello.txt".into(), b"hello world".to_vec()),
16//!     ]))
17//!     .build()
18//!     .unwrap();
19//!
20//! let result = shell.exec("cat /hello.txt").unwrap();
21//! assert_eq!(result.stdout, "hello world");
22//! assert_eq!(result.exit_code, 0);
23//! ```
24//!
25//! # Features
26//!
27//! - **80+ built-in commands** — echo, cat, grep, awk, sed, jq, find, sort, diff, curl, and more
28//! - **Full bash syntax** — pipelines, redirections, variables, control flow, functions,
29//!   command substitution, globs, brace expansion, arithmetic, here-documents, case statements
30//! - **Execution limits** — 10 configurable bounds (time, commands, loops, output size, etc.)
31//! - **Network policy** — sandboxed `curl` with URL allow-lists and method restrictions
32//! - **Multiple filesystem backends** — [`InMemoryFs`], [`OverlayFs`], [`ReadWriteFs`], [`MountableFs`]
33//! - **Custom commands** — implement the [`VirtualCommand`] trait to add your own
34//! - **C FFI and WASM** — embed in any language via shared library or WebAssembly
35
36pub mod api;
37pub mod commands;
38pub mod error;
39pub mod interpreter;
40pub mod platform;
41pub mod vfs;
42
43#[cfg(feature = "network")]
44pub mod network;
45#[cfg(not(feature = "network"))]
46pub mod network {
47    //! Stub network module when the `network` feature is disabled.
48    //! NOTE: This struct must stay in sync with `src/network.rs`.
49    use std::collections::HashSet;
50    use std::time::Duration;
51
52    #[derive(Clone, Debug)]
53    pub struct NetworkPolicy {
54        pub enabled: bool,
55        pub allowed_url_prefixes: Vec<String>,
56        pub allowed_methods: HashSet<String>,
57        pub max_redirects: usize,
58        pub max_response_size: usize,
59        pub timeout: Duration,
60    }
61
62    impl Default for NetworkPolicy {
63        fn default() -> Self {
64            Self {
65                enabled: false,
66                allowed_url_prefixes: Vec::new(),
67                allowed_methods: HashSet::from(["GET".to_string(), "POST".to_string()]),
68                max_redirects: 5,
69                max_response_size: 10 * 1024 * 1024,
70                timeout: Duration::from_secs(30),
71            }
72        }
73    }
74
75    impl NetworkPolicy {
76        pub fn validate_url(&self, _url: &str) -> Result<(), String> {
77            Err("network feature is disabled".to_string())
78        }
79
80        pub fn validate_method(&self, _method: &str) -> Result<(), String> {
81            Err("network feature is disabled".to_string())
82        }
83    }
84}
85
86pub use api::{RustBash, RustBashBuilder};
87pub use commands::{CommandContext, CommandResult, ExecCallback, VirtualCommand};
88pub use error::{RustBashError, VfsError};
89pub use interpreter::{
90    ExecResult, ExecutionCounters, ExecutionLimits, InterpreterState, ShellOpts, Variable,
91    VariableAttrs, VariableValue, builtin_names,
92};
93pub use network::NetworkPolicy;
94pub use vfs::{DirEntry, InMemoryFs, Metadata, MountableFs, NodeType, VirtualFs};
95
96#[cfg(feature = "native-fs")]
97pub use vfs::{OverlayFs, ReadWriteFs};
98
99#[cfg(feature = "ffi")]
100pub mod ffi;
101
102#[cfg(feature = "cli")]
103pub mod mcp;
104
105#[cfg(feature = "wasm")]
106pub mod wasm;
107
108#[cfg(test)]
109mod parser_smoke_tests;