import type { ChildProcess } from 'node:child_process'; import type { FsReadRestrictionConfig, FsWriteRestrictionConfig } from './sandbox-schemas.js'; export interface LinuxNetworkBridgeContext { httpSocketPath: string; socksSocketPath: string; httpBridgeProcess: ChildProcess; socksBridgeProcess: ChildProcess; httpProxyPort: number; socksProxyPort: number; } export interface LinuxSandboxParams { command: string; needsNetworkRestriction: boolean; httpSocketPath?: string; socksSocketPath?: string; httpProxyPort?: number; socksProxyPort?: number; readConfig?: FsReadRestrictionConfig; writeConfig?: FsWriteRestrictionConfig; enableWeakerNestedSandbox?: boolean; allowAllUnixSockets?: boolean; binShell?: string; ripgrepConfig?: { command: string; args?: string[]; }; /** Maximum directory depth to search for dangerous files (default: 3) */ mandatoryDenySearchDepth?: number; /** Allow writes to .git/config files (default: false) */ allowGitConfig?: boolean; /** Custom seccomp binary paths */ seccompConfig?: { bpfPath?: string; applyPath?: string; }; /** Abort signal to cancel the ripgrep scan */ abortSignal?: AbortSignal; } /** * Clean up mount point files created by bwrap for non-existent deny paths. * * When protecting non-existent deny paths, bwrap creates empty files on the * host filesystem as mount points for --ro-bind. These files persist after * bwrap exits. This function removes them. * * This should be called after each sandboxed command completes to prevent * ghost dotfiles (e.g. .bashrc, .gitconfig) from appearing in the working * directory. It is also called automatically on process exit as a safety net. * * Each call decrements the active-sandbox counter that was incremented by * wrapCommandWithSandboxLinux(). File deletion is deferred until the counter * reaches zero. Deleting a mount point file on the host while another bwrap * instance is still running detaches that instance's bind mount (the dentry * is unhashed, so path lookup no longer finds the mount) and the deny rule * stops applying inside that sandbox. * * Pass `{ force: true }` to delete unconditionally — used by the process-exit * handler and reset() where deferral is not meaningful. */ export declare function cleanupBwrapMountPoints(opts?: { force?: boolean; }): void; /** * Detailed status of Linux sandbox dependencies */ export type LinuxDependencyStatus = { hasBwrap: boolean; hasSocat: boolean; hasSeccompBpf: boolean; hasSeccompApply: boolean; }; /** * Result of checking sandbox dependencies */ export type SandboxDependencyCheck = { warnings: string[]; errors: string[]; }; /** * Get detailed status of Linux sandbox dependencies */ export declare function getLinuxDependencyStatus(seccompConfig?: { bpfPath?: string; applyPath?: string; }): LinuxDependencyStatus; /** * Check sandbox dependencies and return structured result */ export declare function checkLinuxDependencies(seccompConfig?: { bpfPath?: string; applyPath?: string; }): SandboxDependencyCheck; /** * Initialize the Linux network bridge for sandbox networking * * ARCHITECTURE NOTE: * Linux network sandboxing uses bwrap --unshare-net which creates a completely isolated * network namespace with NO network access. To enable network access, we: * * 1. Host side: Run socat bridges that listen on Unix sockets and forward to host proxy servers * - HTTP bridge: Unix socket -> host HTTP proxy (for HTTP/HTTPS traffic) * - SOCKS bridge: Unix socket -> host SOCKS5 proxy (for SSH/git traffic) * * 2. Sandbox side: Bind the Unix sockets into the isolated namespace and run socat listeners * - HTTP listener on port 3128 -> HTTP Unix socket -> host HTTP proxy * - SOCKS listener on port 1080 -> SOCKS Unix socket -> host SOCKS5 proxy * * 3. Configure environment: * - HTTP_PROXY=http://localhost:3128 for HTTP/HTTPS tools * - GIT_SSH_COMMAND with socat for SSH through SOCKS5 * * LIMITATION: Unlike macOS sandbox which can enforce domain-based allowlists at the kernel level, * Linux's --unshare-net provides only all-or-nothing network isolation. Domain filtering happens * at the host proxy level, not the sandbox boundary. This means network restrictions on Linux * depend on the proxy's filtering capabilities. * * DEPENDENCIES: Requires bwrap (bubblewrap) and socat */ export declare function initializeLinuxNetworkBridge(httpProxyPort: number, socksProxyPort: number): Promise; /** * Wrap a command with sandbox restrictions on Linux * * UNIX SOCKET BLOCKING (APPLY-SECCOMP): * This implementation uses a custom apply-seccomp binary to block Unix domain socket * creation for user commands while allowing network infrastructure: * * Stage 1: Outer bwrap - Network and filesystem isolation (NO seccomp) * - Bubblewrap starts with isolated network namespace (--unshare-net) * - Bubblewrap applies PID namespace isolation (--unshare-pid and --proc) * - Filesystem restrictions are applied (read-only mounts, bind mounts, etc.) * - Socat processes start and connect to Unix socket bridges (can use socket(AF_UNIX, ...)) * * Stage 2: apply-seccomp - Nested PID namespace + seccomp filter * - apply-seccomp creates a nested user+PID+mount namespace and remounts /proc * - Inside, apply-seccomp becomes PID 1 (non-dumpable init/reaper) * - Forks, sets PR_SET_NO_NEW_PRIVS, applies seccomp via prctl(PR_SET_SECCOMP) * - Execs user command with seccomp active (cannot create new Unix sockets) * - User command cannot see or ptrace bwrap/bash/socat (separate PID namespace) * * This solves the conflict between: * - Security: Blocking arbitrary Unix socket creation in user commands * - Functionality: Network sandboxing requires socat to call socket(AF_UNIX, ...) for bridge connections * * The seccomp-bpf filter blocks socket(AF_UNIX, ...) syscalls, preventing: * - Creating new Unix domain socket file descriptors * * Security limitations: * - Does NOT block operations (bind, connect, sendto, etc.) on inherited Unix socket FDs * - Does NOT prevent passing Unix socket FDs via SCM_RIGHTS * - For most sandboxing use cases, blocking socket creation is sufficient * * The filter allows: * - All TCP/UDP sockets (AF_INET, AF_INET6) for normal network operations * - All other syscalls * * PLATFORM NOTE: * The allowUnixSockets configuration is not path-based on Linux (unlike macOS) * because seccomp-bpf cannot inspect user-space memory to read socket paths. * * Requirements for seccomp filtering: * - Pre-built apply-seccomp binaries are included for x64 and ARM64 * - Pre-generated BPF filters are included for x64 and ARM64 * - Other architectures are not currently supported (no apply-seccomp binary available) * - To use sandboxing without Unix socket blocking on unsupported architectures, * set allowAllUnixSockets: true in your configuration * Dependencies are checked by checkLinuxDependencies() before enabling the sandbox. */ export declare function wrapCommandWithSandboxLinux(params: LinuxSandboxParams): Promise; //# sourceMappingURL=linux-sandbox-utils.d.ts.map