Files
admin 875c7f9b91 feat: Complete zCode CLI X with Telegram bot integration
- 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
2026-05-05 09:01:26 +00:00

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