Greywall Sandbox

repository·main·Indexed 42 days ago

https://github.com/greyhavenhq/greywall

A container-free sandbox for AI coding agents on Linux and macOS. It provides high-security isolation for filesystem and network access using kernel-enforced mechanisms like Bubblewrap, Landlock, and sandbox-exec (Seatbelt) without the overhead of Docker. Features include deny-by-default security, a learning mode for automatic profile generation, and an observability mode called greywatch.

Tokens
27.5K
Snippets
97
Records
148
Agent score
55%

What's inside Greywall

  1. Extend templates and config files using the extends field

    main

    You can build upon existing templates or other configuration files using the extends field in your JSON configuration. This prevents duplication and allows for modular security policies.

    Extending Templates

    Use the name of a built-in template (e.g., "extends": "code").

    Extending Files

    Use a file path (e.g., "extends": "./shared/base-config.json"). The value is treated as a file path if it contains / or \, or starts with .. Relative paths are resolved relative to the config file's directory.

    Merging Logic

    When extending, settings are merged according to these rules:

    • Slice fields (e.g., paths, commands): Values are appended and deduplicated.
    • Boolean fields: Uses OR logic (the field is true if either the base or the extension enables it).
    • Integer fields (e.g., ports): The extension value overrides the base value (use 0 in the extension to keep the base value).

    Chains are supported (File A extends Template B, File C extends File A), but circular extensions are rejected.

    {
      "extends": "code",
      "filesystem": {
        "allowWrite": [ ".", "/tmp" ]
      }
    }
  2. How the macOS network sandbox works

    main

    On macOS, Greywall uses sandbox-exec with a generated Seatbelt profile. This profile denies all outbound network connections by default, with a single exception: connections to Greyproxy's HTTP and SOCKS5 ports on localhost.

    Traffic Flow:

    • Proxy Routing: Greywall sets HTTP_PROXY, HTTPS_PROXY, and ALL_PROXY in the sandboxed process's environment. Applications that honor these variables will route through Greyproxy.
    • Non-Proxy Aware Applications: Applications that ignore proxy environment variables will hit the Seatbelt denial and fail to connect. This is a deliberate design choice to prevent silent bypasses; a hard failure is preferred over an unmonitored connection.

    Note that unlike Linux, macOS does not use a TUN device or DNS bridge, so it lacks transparent network capture. The security guarantee relies on the Seatbelt profile blocking any connection that isn't explicitly routed to the proxy.

    flowchart LR
        subgraph Sandbox["Sandbox (sandbox-exec profile)"]
            CMD["User command"]
        end
    
        Greyproxy["Greyproxy<br/>HTTP and SOCKS5 proxy"]
    
        CMD -->|HTTP_PROXY, HTTPS_PROXY, ALL_PROXY| Greyproxy
  3. Understand the Greywall security model and limitations

    main

    Greywall is designed for controlling agent behavior and preventing accidental permission inheritance, but it is not a hardened containment boundary for actively malicious code.

    What Greywall does NOT do:

    • Prevent resource exhaustion (CPU, memory, disk).
    • Prevent timing attacks.
    • Prevent kernel-level escapes.
    • Perform content inspection on allowed hosts (it only allows the domain/host).

    Recommendation: If you need to inspect the actual data flowing over an allowed network connection, pair Greywall with Greyproxy.

  4. Expose and forward ports in the sandbox

    main

    Greywall provides two ways to manage network connectivity for sandboxed processes:

    1. Expose a port (--port / -p): Use this to allow external processes on your host to connect to a server running inside the sandbox.
    2. Forward a port (--forward / -f): Use this to allow a process inside the sandbox to reach a service running on your host (e.g., a local database).

    On Linux, port forwarding uses a socat bridge through the isolated network namespace. On macOS, it uses a targeted Seatbelt allow rule.

    # Single port exposure
    greywall -p 3000 -c "npm run dev"
    
    # Multiple port exposure
    greywall -p 3000 -p 8080 -c "make start"
    
    # Reach a host Postgres from inside the sandbox
    greywall -f 5432 -- psql -h localhost
    
    # Forward multiple ports
    greywall -f 5432 -f 6379 -- make test
  5. How Greywall sandboxes commands

    main

    Greywall provides a multi-layered security approach to restrict network, filesystem, and command access for arbitrary processes. It achieves isolation through four primary mechanisms:

    1. Command Blocking: Uses configurable deny/allow lists to intercept and block dangerous commands (e.g., rm -rf, reboot) before they execute. It includes chain detection for pipelines (&&, |) and nested shells (bash -c).
    2. Network Routing: Routes traffic through an external SOCKS5 proxy (like GreyProxy) using transparent TUN-based proxying on Linux or environment variables on macOS.
    3. Process Sandboxing: Utilizes OS-native mechanisms: sandbox-exec (Seatbelt) on macOS and bubblewrap (bwrap) on Linux.
    4. Environment Sanitization: Strips dangerous environment variables (e.g., LD_PRELOAD on Linux, DYLD_INSERT_LIBRARIES on macOS) to prevent library injection attacks.
  6. How Credential Protection works in Greywall

    main

    Greywall protects API keys and secrets by preventing sandboxed processes from seeing real values. Instead of the actual secret, the sandboxed environment receives an opaque placeholder (e.g., greyproxy:credential:v1:gw-<id>:<digest>).

    When the sandboxed process makes an HTTP request, greyproxy (v0.3.4+) intercepts the request and substitutes the placeholder with the real credential in the HTTP headers or URL query parameters before forwarding it upstream.

    Key constraints:

    • Does NOT protect request bodies: If an API requires credentials in the body, it will receive the placeholder string instead of the real secret.
    • Does NOT protect non-HTTP protocols: Raw TCP and WebSocket frames are not inspected.
    • Requires greyproxy: This feature requires greyproxy v0.3.4 or later.
  7. Configure localhost and port access

    main

    Greywall provides granular controls for interacting with localhost services. These controls behave differently depending on your operating system.

    Configuration Options

    • allowLocalBinding: Allows a sandboxed process to listen on local ports (e.g., starting a dev server).
    • allowLocalOutbound: Allows a sandboxed process to connect to host localhost services (macOS only).
    • -p/--port: Exposes an inbound port so external entities can reach a server inside the sandbox.
    • -f/--forward: Forwards a specific host localhost port into the sandbox.
    • forwardPorts: The configuration file equivalent of -f.

    Platform Comparison

    FeaturemacOSLinux
    Sandbox connects to host localhostallowLocalOutbound: true (all ports) or -f <port> (specific ports)-f <port> or forwardPorts: [port]
    Host connects to sandbox port-p <port>-p <port>
    Sandbox listens on local portallowLocalBinding: trueallowLocalBinding: true

    Usage Examples

    Connecting to a Postgres server on host port 5432:

    On macOS, you can enable all localhost outbound access:

    # macOS: allowLocalOutbound in the config is enough
    greywall -- psql -h localhost

    On Linux, you must explicitly forward the specific port because the host's localhost is in a different network namespace:

    # Linux: the specific port must be forwarded
    greywall -f 5432 -- psql -h localhost
    # macOS: allowLocalOutbound in the config is enough
    greywall -- psql -h localhost
    
    # Linux: the specific port must be forwarded
    greywall -f 5432 -- psql -h localhost
  8. Understand the Greywall Security Model

    main

    Greywall is designed as a defense-in-depth tool for running semi-trusted commands (such as package installs, build scripts, or CI jobs) with reduced side effects.

    Key Use Cases:

    • Preventing supply-chain scripts from unexpected network calls.
    • Restricting tools that write broadly across the filesystem.
    • Preventing accidental leakage of secrets via "phone home" behavior.
    • Isolating unfamiliar repositories during install/build/test.

    Critical Limitations:

    • Not a strong isolation boundary: It is not designed to stop actively malicious code attempting to escape via kernel/OS vulnerabilities.
    • No resource limits: It does not manage CPU, memory, disk usage, or fork bombs.
    • No content inspection: It does not inspect the content of network requests; access control is delegated to an external proxy.
    • No data exfiltration blocking: It does not block data exfiltration to destinations that have already been allowed.
  9. How the Linux network sandbox works

    main

    On Linux, Greywall uses bubblewrap with the --unshare-net flag to create an isolated network namespace for the sandboxed command. This ensures the command cannot reach the host network directly.

    Traffic Flow:

    • Outbound Traffic: All traffic is routed through a TUN device inside the namespace. tun2socks reads packets from this device and forwards them via a Unix-socket bridge to Greyproxy's HTTP and SOCKS5 proxy on the host. This capture is transparent and works even for applications that ignore proxy environment variables (e.g., Node.js built-in http/https).
    • DNS: A DNS bridge inside the namespace forwards queries via a Unix-socket to Greyproxy's DNS proxy, ensuring name resolution follows the same filtered path.

    Fallback Behavior: If a TUN device is unavailable (e.g., inside a container without /dev/net/tun), Greywall falls back to setting HTTP_PROXY, HTTPS_PROXY, and ALL_PROXY environment variables inside the namespace. In this mode, only applications that honor these variables are routed; others are blocked by the namespace isolation.

    flowchart LR
        subgraph Sandbox["Sandbox (bwrap --unshare-net)"]
            CMD["User command"]
            TUN["tun2socks<br/>(TUN device)"]
            DNSBR["DNS bridge"]
        end
    
        subgraph Greyproxy
            PROXY["HTTP and SOCKS5 proxy"]
            DNSPROXY["DNS proxy"]
        end
    
        CMD -->|all outbound traffic| TUN
        CMD -->|DNS queries| DNSBR
        TUN -->|Unix socket| PROXY
        DNSBR -->|Unix socket| DNSPROXY
  10. How Greywall provides sandboxing for AI agents

    main

    Greywall is a default-deny sandbox designed to wrap local AI agents or commands. It enforces boundaries at the OS layer (using sandbox-exec on macOS and bubblewrap with Linux namespaces on Linux), ensuring that permissions apply below the agent process and cannot be bypassed by the agent's own tooling.

    Greywall manages four primary dimensions of access:

    • Filesystem: Writes are denied by default. You must explicitly grant access to specific directories. Sensitive paths remain denied even if they reside within an allowed directory.
    • Network: Outbound traffic is denied by default. You can allow specific hosts or use Greyproxy for advanced rule matching, MITM inspection, and credential substitution.
    • Commands: You can block dangerous command patterns, such as rm -rf /, sudo, or package managers targeting system paths.
    • Observability: Every blocked attempt, allowed connection, and file touch is recorded, providing a real-time audit trail of agent activity.
  11. Use config inheritance and templates

    main

    You can reduce boilerplate by using the extends field to inherit settings from built-in templates or other configuration files.

    Extending a template

    If the extends value does not contain / or \ and does not start with ., it is treated as a template name (e.g., code).

    {
      "extends": "code",
      "filesystem": {
        "allowWrite": [".", "/tmp"]
      }
    }

    Extending a file

    Use absolute or relative paths to extend other files. Relative paths are resolved relative to the current config file's directory.

    {
      "extends": "./base-config.json",
      "command": {
        "deny": ["git push"]
      }
    }

    Merge Behavior

    • Slice fields (paths, commands): Appended and deduplicated.
    • Boolean fields: Uses OR logic (true if either base or override enables it).
    • Integer fields (ports): Override-wins (setting to 0 keeps the base value).

    Constraints:

    • Maximum chain depth is 10.
    • Circular extends are detected and rejected.
  12. macOS Sandbox Implementation

    main

    On macOS, Greywall utilizes Apple's sandbox-exec with Seatbelt profiles. Profiles are generated dynamically based on the configuration to control:

    • Network: Deny all except localhost (to allow proxying).
    • Filesystem: Selective file-read and file-write rules.
    • Process: Permissions for process-fork and process-exec.

    Unlike Linux, macOS relies on syscall filtering and profile rules for network and filesystem isolation.