- Add full Telegram bot functionality with Z.AI API integration
- Implement 4 tools: Bash, FileEdit, WebSearch, Git
- Add 3 agents: Code Reviewer, Architect, DevOps Engineer
- Add 6 skills for common coding tasks
- Add systemd service file for 24/7 operation
- Add nginx configuration for HTTPS webhook
- Add comprehensive documentation
- Implement WebSocket server for real-time updates
- Add logging system with Winston
- Add environment validation
🤖 zCode CLI X - Agentic coder with Z.AI + Telegram integration
169 lines
7.1 KiB
TypeScript
169 lines
7.1 KiB
TypeScript
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<LinuxNetworkBridgeContext>;
|
|
/**
|
|
* 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<string>;
|
|
//# sourceMappingURL=linux-sandbox-utils.d.ts.map
|