Claude
Skills
Sign in
โ† Back

sandboxing

Included with Lifetime
$97 forever

# Sandboxing Skill

General

What this skill does

# Sandboxing Skill

---
name: sandboxing
version: 1.0.0
domain: security/isolation
risk_level: HIGH
languages: [python, c, rust, go]
frameworks: [seccomp, apparmor, selinux, bubblewrap]
requires_security_review: true
compliance: [SOC2, FedRAMP]
last_updated: 2025-01-15
---

> **MANDATORY READING PROTOCOL**: Before implementing sandboxing, read `references/advanced-patterns.md` for defense-in-depth strategies and `references/threat-model.md` for container escape scenarios.

## 1. Overview

### 1.1 Purpose and Scope

This skill provides process isolation and sandboxing for JARVIS components:

- **Linux**: seccomp-bpf, AppArmor/SELinux, namespaces, cgroups
- **Windows**: AppContainer, Job Objects, Restricted Tokens
- **macOS**: sandbox-exec, App Sandbox entitlements
- **Containers**: Docker/Podman security contexts, Kubernetes SecurityContext

### 1.2 Risk Assessment

**Risk Level**: HIGH

**Justification**:
- Sandbox escapes allow full system compromise
- Misconfigurations negate all isolation benefits
- Kernel vulnerabilities bypass userspace controls
- Plugin/extension execution requires strong isolation

**Attack Surface**:
- Syscall filtering gaps
- Namespace escape vectors
- Capability misconfigurations
- Resource exhaustion attacks

## 2. Core Responsibilities

### 2.1 Primary Functions

1. **Isolate untrusted code** execution from host system
2. **Restrict syscalls** to minimum required set
3. **Limit resources** (CPU, memory, network, filesystem)
4. **Enforce security policies** via MAC (AppArmor/SELinux)
5. **Contain failures** to prevent cascade effects

### 2.2 Core Principles

- **TDD First**: Write tests for sandbox restrictions before implementation
- **Performance Aware**: Cache permissions, lazy-load capabilities, minimize syscall overhead
- **Defense in Depth**: Layer multiple isolation mechanisms
- **Least Privilege**: Grant minimum permissions required
- **Fail Secure**: Default deny all access

### 2.3 Security Principles

- **NEVER** run untrusted code without syscall filtering
- **NEVER** grant CAP_SYS_ADMIN to sandboxed processes
- **ALWAYS** drop all capabilities not explicitly required
- **ALWAYS** use read-only root filesystem where possible
- **ALWAYS** apply defense-in-depth (multiple layers)

## 3. Technology Stack

| Platform | Primary | Secondary | MAC |
|----------|---------|-----------|-----|
| Linux | seccomp-bpf | namespaces | AppArmor/SELinux |
| Windows | AppContainer | Job Objects | WDAC |
| macOS | sandbox-exec | Entitlements | TCC |
| Containers | securityContext | RuntimeClass | Pod Security |

**Recommended Tools**: bubblewrap, firejail, nsjail, gVisor

## 4. Implementation Patterns

### 4.1 Seccomp-BPF Filter (python-seccomp)

```python
import seccomp
import os

def create_minimal_sandbox():
    """Create minimal seccomp sandbox for untrusted code."""
    filter = seccomp.SyscallFilter(defaction=seccomp.KILL)

    # Essential syscalls
    essential = [
        'read', 'write', 'close', 'fstat', 'lseek',
        'mmap', 'mprotect', 'munmap', 'brk',
        'rt_sigaction', 'rt_sigprocmask', 'rt_sigreturn',
        'exit', 'exit_group', 'futex', 'clock_gettime',
    ]

    for syscall in essential:
        filter.add_rule(seccomp.ALLOW, syscall)

    return filter

def run_sandboxed(func, *args, **kwargs):
    """Execute function in seccomp sandbox."""
    filter = create_minimal_sandbox()
    pid = os.fork()

    if pid == 0:
        filter.load()
        try:
            func(*args, **kwargs)
            os._exit(0)
        except Exception:
            os._exit(1)
    else:
        _, status = os.waitpid(pid, 0)
        return os.WEXITSTATUS(status) == 0
```

**๐Ÿ“š For custom BPF filters and advanced seccomp**:
- See `references/advanced-patterns.md#seccomp-bpf`

### 4.2 Bubblewrap Sandbox (Recommended)

```python
import subprocess
from typing import List

class BubblewrapSandbox:
    """High-level sandboxing using bubblewrap."""

    def __init__(self):
        self._args = ['bwrap']

    def with_minimal_filesystem(self) -> 'BubblewrapSandbox':
        self._args.extend([
            '--ro-bind', '/usr', '/usr',
            '--ro-bind', '/lib', '/lib',
            '--ro-bind', '/lib64', '/lib64',
            '--symlink', 'usr/bin', '/bin',
            '--proc', '/proc', '--dev', '/dev',
            '--tmpfs', '/tmp',
        ])
        return self

    def with_network_isolation(self) -> 'BubblewrapSandbox':
        self._args.append('--unshare-net')
        return self

    def drop_capabilities(self) -> 'BubblewrapSandbox':
        self._args.append('--cap-drop ALL')
        return self

    def run(self, command: List[str], timeout: int = 30):
        return subprocess.run(
            self._args + ['--'] + command,
            capture_output=True, timeout=timeout
        )

# Usage
def run_untrusted_script(script_path: str) -> str:
    sandbox = BubblewrapSandbox()
    sandbox.with_minimal_filesystem().with_network_isolation().drop_capabilities()
    result = sandbox.run(['python3', script_path], timeout=10)
    return result.stdout.decode()
```

**๐Ÿ“š For namespace isolation and advanced bubblewrap**:
- See `references/advanced-patterns.md#namespaces`

### 4.3 Kubernetes SecurityContext

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: jarvis-worker
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 1000
    seccompProfile:
      type: RuntimeDefault

  containers:
  - name: worker
    image: jarvis-worker:latest
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: [ALL]

    resources:
      limits:
        cpu: "1"
        memory: "512Mi"

    volumeMounts:
    - name: tmp
      mountPath: /tmp

  volumes:
  - name: tmp
    emptyDir:
      medium: Memory
      sizeLimit: 64Mi
```

## 5. Implementation Workflow (TDD)

### Step 1: Write Failing Test First

```python
import pytest
from sandbox import SandboxManager

class TestSandboxRestrictions:
    """Test sandbox isolation before implementation."""

    @pytest.fixture
    def sandbox(self):
        return SandboxManager()

    def test_network_blocked(self, sandbox):
        """WRITE FIRST: Network access must be blocked."""
        result = sandbox.run(['curl', '-s', 'http://example.com'])
        assert result.returncode != 0, "Network should be blocked"

    def test_filesystem_readonly(self, sandbox):
        """WRITE FIRST: Root filesystem must be read-only."""
        result = sandbox.run(['touch', '/test-file'])
        assert result.returncode != 0, "Root FS should be read-only"

    def test_capabilities_dropped(self, sandbox):
        """WRITE FIRST: All capabilities must be dropped."""
        result = sandbox.run(['cat', '/proc/self/status'])
        assert 'CapEff:\t0000000000000000' in result.stdout

    def test_syscall_blocked(self, sandbox):
        """WRITE FIRST: Dangerous syscalls must be blocked."""
        # ptrace should be blocked by seccomp
        result = sandbox.run(['strace', 'ls'])
        assert result.returncode != 0, "ptrace should be blocked"

    def test_escape_attempt_fails(self, sandbox):
        """WRITE FIRST: Container escape must fail."""
        result = sandbox.run(['ls', '/proc/1/root'])
        assert result.returncode != 0, "Namespace escape blocked"
```

### Step 2: Implement Minimum to Pass

```python
class SandboxManager:
    def __init__(self):
        self._bwrap_args = ['bwrap', '--unshare-net', '--ro-bind', '/', '/',
                           '--cap-drop', 'ALL', '--seccomp', '3']

    def run(self, command, timeout=30):
        import subprocess
        return subprocess.run(self._bwrap_args + ['--'] + command,
                              capture_output=True, text=True, timeout=timeout)
```

### Step 3: Refactor with Defense-in-Depth

```python
class SandboxManager:
    def __init__(self, profile: str = 'strict'):
        self._bwrap_args = ['bwrap', '--unshare-all']
        if profile ==

Related in General