Skip to content

fix(sandbox): harden seccomp, inference routing, and process limits#869

Merged
johntmyers merged 4 commits intomainfrom
fix/sandbox-security-hardening
Apr 17, 2026
Merged

fix(sandbox): harden seccomp, inference routing, and process limits#869
johntmyers merged 4 commits intomainfrom
fix/sandbox-security-hardening

Conversation

@johntmyers
Copy link
Copy Markdown
Collaborator

Summary

Three defense-in-depth fixes for sandbox security controls, addressing findings from a 2026-04-16 security assessment. Each fix is a separate commit.

  • SEC-01 (OS-94): Block AF_NETLINK in seccomp unconditionally — previously only blocked in NetworkMode::Block, now blocked in all modes alongside AF_PACKET/AF_BLUETOOTH/AF_VSOCK. Impact was informational (network namespace already scopes netlink to sandbox's own veth), but closes the gap.
  • SEC-02 (OS-95): Scope inference.local pre-OPA interception to port 443 only — the hostname-only check at proxy.rs:357 allowed any port to bypass OPA policy evaluation, including under deny-all. Non-443 ports now fall through to OPA.
  • SEC-03 (OS-96): Enforce RLIMIT_NPROC (hard limit 512) in harden_child_process() — prevents fork bomb process exhaustion, most relevant for local dev mode where K8s pod cgroup pids.max is absent.

Related Issues

Closes OS-93, OS-94, OS-95, OS-96

Changes

  • crates/openshell-sandbox/src/sandbox/linux/seccomp.rs — move AF_NETLINK to unconditional block list
  • crates/openshell-sandbox/src/proxy.rs — add INFERENCE_LOCAL_PORT constant and port check to inference interception condition
  • crates/openshell-sandbox/src/process.rs — add RLIMIT_NPROC hard limit of 512 before privilege drop

Testing

  • cargo check -p openshell-sandbox — compiles clean (no new warnings)
  • mise run pre-commit — lint and format
  • mise run test — unit tests
  • mise run e2e — end-to-end validation of deny-all + inference routing + fork limit

Move AF_NETLINK to the unconditional socket-domain block list alongside
AF_PACKET, AF_BLUETOOTH, and AF_VSOCK. Previously it was only blocked in
NetworkMode::Block, leaving it accessible in Proxy mode where network
namespace isolation already scopes netlink to the sandbox's own veth —
making this a defense-in-depth hardening rather than a live exposure.

Closes OS-94
The pre-OPA interception for inference.local matched on hostname alone,
allowing any port to bypass OPA policy evaluation — including under
deny-all (network_policies: {}). Add a port check so only port 443
takes the interception path; all other ports on inference.local now
fall through to OPA and are subject to normal policy evaluation.

Closes OS-95
Set a hard limit of 512 processes per UID in harden_child_process(),
applied before privilege drop so the sandbox user cannot raise it.
Prevents unrestricted fork() from exhausting the process table — most
relevant for local dev mode where K8s pod cgroup pids.max is absent.

Closes OS-96
@johntmyers johntmyers requested a review from a team as a code owner April 17, 2026 00:46
@copy-pr-bot
Copy link
Copy Markdown

copy-pr-bot Bot commented Apr 17, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@johntmyers johntmyers added the test:e2e Requires end-to-end coverage label Apr 17, 2026
@johntmyers johntmyers merged commit 4e8dbcf into main Apr 17, 2026
14 checks passed
@johntmyers johntmyers deleted the fix/sandbox-security-hardening branch April 17, 2026 15:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:e2e Requires end-to-end coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants