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
16 changes: 16 additions & 0 deletions crates/openshell-sandbox/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@ pub(crate) fn harden_child_process() -> Result<()> {
));
}

// Limit process creation to prevent fork bombs. 512 processes per UID is
// sufficient for typical agent workloads (shell, compilers, language servers)
// while preventing runaway forking. Set as a hard limit so the sandbox user
// cannot raise it after privilege drop.
let nproc_limit = libc::rlimit {
rlim_cur: 512,
rlim_max: 512,
};
let rc = unsafe { libc::setrlimit(libc::RLIMIT_NPROC, &nproc_limit) };
if rc != 0 {
return Err(miette::miette!(
"Failed to set RLIMIT_NPROC: {}",
std::io::Error::last_os_error()
));
}

#[cfg(target_os = "linux")]
{
let rc = unsafe { libc::prctl(libc::PR_SET_DUMPABLE, 0, 0, 0, 0) };
Expand Down
3 changes: 2 additions & 1 deletion crates/openshell-sandbox/src/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use tracing::{debug, warn};

const MAX_HEADER_BYTES: usize = 8192;
const INFERENCE_LOCAL_HOST: &str = "inference.local";
const INFERENCE_LOCAL_PORT: u16 = 443;

/// Maximum total bytes for a streaming inference response body (32 MiB).
const MAX_STREAMING_BODY: usize = 32 * 1024 * 1024;
Expand Down Expand Up @@ -354,7 +355,7 @@ async fn handle_tcp_connection(
let (host, port) = parse_target(target)?;
let host_lc = host.to_ascii_lowercase();

if host_lc == INFERENCE_LOCAL_HOST {
if host_lc == INFERENCE_LOCAL_HOST && port == INFERENCE_LOCAL_PORT {
respond(&mut client, b"HTTP/1.1 200 Connection Established\r\n\r\n").await?;
let outcome = handle_inference_interception(
client,
Expand Down
8 changes: 6 additions & 2 deletions crates/openshell-sandbox/src/sandbox/linux/seccomp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,15 @@ fn build_filter_rules(allow_inet: bool) -> Result<BTreeMap<i64, Vec<SeccompRule>
let mut rules: BTreeMap<i64, Vec<SeccompRule>> = BTreeMap::new();

// --- Socket domain blocks ---
let mut blocked_domains = vec![libc::AF_PACKET, libc::AF_BLUETOOTH, libc::AF_VSOCK];
let mut blocked_domains = vec![
libc::AF_PACKET,
libc::AF_BLUETOOTH,
libc::AF_VSOCK,
libc::AF_NETLINK,
];
if !allow_inet {
blocked_domains.push(libc::AF_INET);
blocked_domains.push(libc::AF_INET6);
blocked_domains.push(libc::AF_NETLINK);
}

for domain in blocked_domains {
Expand Down
Loading