zeroclaw/src/security/bubblewrap.rs
Chummy 1711f140be fix(security): remediate unassigned CodeQL findings
- harden URL/request handling for composio and whatsapp integrations
- reduce cleartext logging exposure across providers/tools/gateway
- hash and constant-time compare gateway webhook secrets
- expand nested secret encryption coverage in config
- align feature aliases and add regression tests for security paths
- fix bubblewrap all-features test invocation surfaced during deep validation
2026-02-17 19:19:06 +08:00

97 lines
2.3 KiB
Rust

//! Bubblewrap sandbox (user namespaces for Linux/macOS)
use crate::security::traits::Sandbox;
use std::process::Command;
/// Bubblewrap sandbox backend
#[derive(Debug, Clone, Default)]
pub struct BubblewrapSandbox;
impl BubblewrapSandbox {
pub fn new() -> std::io::Result<Self> {
if Self::is_installed() {
Ok(Self)
} else {
Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
"Bubblewrap not found",
))
}
}
pub fn probe() -> std::io::Result<Self> {
Self::new()
}
fn is_installed() -> bool {
Command::new("bwrap")
.arg("--version")
.output()
.map(|o| o.status.success())
.unwrap_or(false)
}
}
impl Sandbox for BubblewrapSandbox {
fn wrap_command(&self, cmd: &mut Command) -> std::io::Result<()> {
let program = cmd.get_program().to_string_lossy().to_string();
let args: Vec<String> = cmd
.get_args()
.map(|s| s.to_string_lossy().to_string())
.collect();
let mut bwrap_cmd = Command::new("bwrap");
bwrap_cmd.args([
"--ro-bind",
"/usr",
"/usr",
"--dev",
"/dev",
"--proc",
"/proc",
"--bind",
"/tmp",
"/tmp",
"--unshare-all",
"--die-with-parent",
]);
bwrap_cmd.arg(&program);
bwrap_cmd.args(&args);
*cmd = bwrap_cmd;
Ok(())
}
fn is_available(&self) -> bool {
Self::is_installed()
}
fn name(&self) -> &str {
"bubblewrap"
}
fn description(&self) -> &str {
"User namespace sandbox (requires bwrap)"
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bubblewrap_sandbox_name() {
let sandbox = BubblewrapSandbox;
assert_eq!(sandbox.name(), "bubblewrap");
}
#[test]
fn bubblewrap_is_available_only_if_installed() {
// Result depends on whether bwrap is installed
let sandbox = BubblewrapSandbox;
let _available = sandbox.is_available();
// Either way, the name should still work
assert_eq!(sandbox.name(), "bubblewrap");
}
}