https://github.com/santhsecurity/procjail
Process sandbox for untrusted code — Linux namespaces, firejail, bubblewrap, watchdog timeout
https://github.com/santhsecurity/procjail
Last synced: 2 months ago
JSON representation
Process sandbox for untrusted code — Linux namespaces, firejail, bubblewrap, watchdog timeout
- Host: GitHub
- URL: https://github.com/santhsecurity/procjail
- Owner: santhsecurity
- License: mit
- Created: 2026-03-26T01:28:25.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-04-25T23:04:43.000Z (3 months ago)
- Last Synced: 2026-04-26T01:12:21.089Z (3 months ago)
- Language: Rust
- Homepage: https://santh.dev
- Size: 71.3 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# procjail
Run untrusted code in a sandbox. procjail picks the best containment strategy available on the system (bubblewrap > firejail > unshare > rlimits), strips secret environment variables, enforces timeouts, and reports resource usage.
Linux only. procjail relies on Linux process isolation primitives and sandbox launchers such as `bubblewrap`, `firejail`, and `unshare`.
```rust,no_run
use procjail::{SandboxConfig, SandboxedProcess};
use std::{fs, path::Path};
let config = SandboxConfig::builder()
.runtime("sh")
.max_memory_mb(256)
.timeout_seconds(5)
.build();
let work_dir = std::env::temp_dir().join("procjail-readme-example");
fs::create_dir_all(&work_dir)?;
let harness = work_dir.join("harness.sh");
fs::write(
&harness,
"#!/bin/sh\nwhile IFS= read -r line; do printf '{\"echo\":%s}\\n' \"$line\"; done\n",
)?;
let mut proc = SandboxedProcess::spawn(
Path::new(&harness),
Path::new(&work_dir),
&config,
)?;
proc.send("42")?;
let response = proc.recv()?;
println!("{response:?}");
# Ok::<(), procjail::ProcjailError>(())
```
## Containment strategies
| Strategy | PID isolation | Network | Filesystem | How |
|----------|:---:|:---:|:---:|-----|
| Bubblewrap | Yes | Yes | Full (ro-bind) | Recommended. Rootless. |
| Firejail | Yes | Yes | Full (--private) | Adds seccomp + rlimits. |
| Unshare | Yes | Yes | Partial (mount ns) | No full FS restriction. |
| RlimitsOnly | No | No | No | Harness enforces limits. Last resort. |
procjail auto-detects which strategies work on the current system. Override with `.strategy(Strategy::Bubblewrap)`.
## Secret stripping
36 environment variables are stripped by default (AWS keys, GitHub tokens, database URLs, API keys). Custom additions via `.env_strip(&["MY_SECRET"])`. The passthrough list cannot re-add stripped secrets.
## Resource reporting
```rust
let usage = proc.wait_with_usage().unwrap();
println!("peak memory: {} bytes", usage.peak_memory_bytes);
println!("cpu time: {:.2}s", usage.cpu_time_secs);
println!("killed by timeout: {}", proc.killed_by_timeout);
```
## Contributing
Pull requests are welcome. There is no such thing as a perfect crate. If you find a bug, a better API, or just a rough edge, open a PR. We review quickly.
## License
MIT. Copyright 2026 CORUM COLLECTIVE LLC.
[](https://crates.io/crates/procjail)
[](https://docs.rs/procjail)