/** * @file LocalSandbox — 进程级沙箱实现 * @description 为每个 Agent 会话提供隔离的文件系统和 Shell 执行环境 * 文件系统限制在沙箱目录内,命令执行受 SecurityGuard + 沙箱黑名单保护 */ import type { ShellExecutor, FileSystemExecutor, Sandbox, SandboxConfig, ScriptLanguage } from '@cicctencent/agent-core'; /** * 过滤环境变量,只保留安全白名单中的变量 */ export declare function filterEnvForSandbox(env: Record): Record; /** * 动态注册沙箱脚本语言(扩展新语言时调用)。 * @param language 语言标识 * @param config 文件扩展名 + 执行命令 */ export declare function registerSandboxLanguage(language: string, config: { ext: string; command: string; }): void; /** * 沙箱文件系统执行器 * 所有路径操作限制在沙箱 rootDir 内,阻止路径穿越 */ export declare class SandboxFileSystemExecutor implements FileSystemExecutor { private readonly rootDir; private readonly maxFileSize; constructor(rootDir: string, maxFileSize: number); readFile(filePath: string): Promise; readFileBuffer(filePath: string): Promise; writeFile(filePath: string, content: string): Promise; appendFile(filePath: string, content: string): Promise; listDir(dirPath: string): Promise; /** * 解析路径并验证是否在沙箱目录内 * 如果路径越界(绝对路径或 .. 穿越),自动修正到沙箱内而非抛错 */ private resolveAndValidate; /** * 解析只读路径 — 允许读取沙箱目录和项目 data/ 目录 * data/ 目录存放对话内容、主题配置等只读资源,read_file 可安全访问 */ private resolveReadPath; } /** * 沙箱 Shell 执行器 * - cwd 限制在沙箱目录 * - 环境变量经过白名单过滤 * - 命令经过 SecurityGuard + 沙箱黑名单检查 */ export declare class SandboxShellExecutor implements ShellExecutor { private readonly rootDir; private readonly commandRestriction; private readonly guard; private outputBuffer; private readonly maxBuffer; private sandboxEnv; /** 当前 OS 用户名,用于脱敏 shell 输出 */ private readonly osUsername; constructor(rootDir: string, commandRestriction: boolean); /** * 注入额外运行时环境变量(如 SB_BACKEND_BASE_URL 等),供沙箱内进程(Python sb 绑定) * 通过 os.environ 读取宿主端点。与 SB_PY_SOURCE 旧版「源码占位符替换」不同, * 新版 data/_shared/work/python/sb.py 统一从 os.environ 读取 host 端点,故此处注入。 */ injectEnv(extra: Record): void; /** * 暴露运行时注入的环境变量快照(含 SB_* 宿主端点),供 LocalSandbox / ProcessCodeSandbox * 在执行物化文件(executeFile)时合并进子进程 env,使 os.environ 能拿到沙箱端点。 */ getSandboxEnvSnapshot(): Record; /** 返回沙箱环境变量快照(含 SB_* 注入),供 LocalSandbox.getSandboxEnv 使用。 */ getEnv(): Record; /** * 脱敏 shell 输出:移除服务器用户名等敏感信息。 * ls -l 输出中的 owner/group 列会暴露服务器用户名。 */ private sanitizeShellOutput; exec(command: string, timeout?: number): Promise; /** * 执行命令并返回结构化结果(含真实退出码与分离的 stdout/stderr)。 * * 旧 exec() 会把子进程失败信息(error.message,如 "Command failed: python3 ...") * 混入 stdout 并吞掉退出码,导致上层(ProcessCodeSandbox.execute)误判为成功。 * execDetailed 透传退出码,并把无输出的失败原因放入 stderr,使失败可被正确识别。 */ execDetailed(command: string, timeout?: number): Promise<{ stdout: string; stderr: string; exitCode: number; output: string; }>; write(_data: string): void; read(lines?: number): string; /** * 检测命令中是否引用了沙箱目录之外的路径。 * 实际逻辑统一收敛在 agent-core 的 path-guard.ts(单一共享来源)。 */ private findOutsideSandboxPath; } /** * 本地沙箱实例 * 封装受限的 Shell 和 FileSystem 执行器,提供 runScript 能力 */ export declare class LocalSandbox implements Sandbox { readonly id: string; readonly rootDir: string; protected readonly config: SandboxConfig; private readonly shellExecutor; private readonly fsExecutor; private readonly scriptsDir; /** 后端服务地址与代理(供 Python/Shell 版 sb 服务接口封装使用) */ private readonly backendBaseUrl; private readonly fetchProxyUrl; private readonly sbScriptToken; constructor(id: string, config: SandboxConfig); /** 初始化沙箱目录(创建后必须调用) */ init(): Promise; /** 将注册的扩展能力写入 _scripts/_prelude_ext/,供 prelude 在 require 时自动合并进 global.sb */ private injectPreludeExtensions; getShellExecutor(): ShellExecutor; /** 获取沙箱环境变量快照(含 SB_* 注入),供子类 ProcessCodeSandbox.executeFile 使用。 */ protected getSandboxEnv(): Record; getFileSystemExecutor(): FileSystemExecutor; /** 获取指定语言的执行命令(供子类 ProcessCodeSandbox.executeStream 使用)。 * Python 命令名(python3 / python)跨环境不一致,运行时探测可用的那一个。 */ protected getLanguageCommand(language: string): Promise; /** * 检查解释器是否可用。 * 对 Python 系列命令,必须以"实际试跑"为准(与真实执行使用同一 shell 通道 `cmd.exe`/`sh`), * 否则在 Windows「应用执行别名」注入 0 字节 `python3.exe` 占位壳时,`command -v`/`where` * 会误判为可用,但实际调用静默失败。Node / Bash 等真实二进制仍用 `command -v` 探测。 * 返回 { ok, hint }:ok=false 时 hint 包含安装建议。 */ private checkInterpreter; runScript(language: ScriptLanguage, code: string, timeout?: number): Promise; /** * 执行脚本并返回结构化结果(含退出码与分离的 stdout/stderr)。 * 供 ProcessCodeSandbox.execute 等需要正确判定成功/失败的场景使用。 */ runScriptDetailed(language: string, code: string, timeout?: number): Promise<{ stdout: string; stderr: string; exitCode: number; output: string; }>; /** * 构建最终脚本源码(注入 prelude / 顶层 await 包裹 / 编码声明)。 */ private buildFinalCode; /** * 构建最终脚本、做安全校验并写入临时脚本文件,返回脚本路径。 * 供 runScriptDetailed(同步执行)、ProcessCodeSandbox.executeStream(流式执行)、 * 以及 skill-resources run_skill_script(技能脚本复用 sb 注入)复用。 */ prepareScript(language: string, code: string): Promise; /** * 安全静态扫描:拦截脚本内容中向沙箱外(用户目录/系统目录)的绝对路径读写, * 以及高危命令 / shell 注入。供 prepareScript 与 runSkillScript 复用。 * * 注意:该扫描仅针对脚本*内容*,不校验脚本的*运行位置*。运行位置由调用方决定 * (沙箱 _scripts/ 或技能包目录)。技能包目录属于受信任用户资产,由 runSkillScript * 直接用 spawn 执行,不经 SandboxShellExecutor 的包外路径拦截,但本扫描仍生效。 */ private scanScriptSecurity; /** * 在脚本所在目录内物化临时脚本并返回路径(不执行)。 * * 与 prepareScript(脚本写到沙箱 _scripts/)不同,本方法把临时脚本写到 * **原始脚本所在的目录**(runDir,通常是技能包内的 scripts/)。这样临时脚本的 * `__file__` 与作者本地运行完全一致,`Path(__file__).parent` 的相对依赖约定 * (兄弟共享库 lib.py/config.py、子目录数据 pool-manager/data/pools.json 等) * 无需任何改动即可正确解析。 * * buildFinalCode 注入的运行时依赖(Python 的 work/python 命名空间包 / Node 的 _prelude.cjs / * Shell 的 sb.sh 等)原本位于沙箱 _scripts/ 下,本方法会把它们复制到 runDir, * 使临时脚本的 `from work.python import sb` / `require('./_prelude')` / * `source "$(dirname "$0")/sb.sh"` 也能正确解析。 * * 调用方应随后以 cwd = packageDir 执行该脚本(如 skill-resources 的 runScript), * 不经过 SandboxShellExecutor 的包外路径拦截——技能包是受信任用户资产, * 且脚本内容已通过 scanScriptSecurity 静态扫描。 * * @param runDir 临时脚本与运行时依赖的物化目录(通常是脚本原始所在目录) * @param packageDir 技能包根目录(调用方用作 cwd;本方法校验 runDir 必须位于其内,纵深防御) */ prepareScriptInPackage(language: string, code: string, runDir: string, packageDir: string): Promise; /** * 将沙箱 _scripts/ 下的运行时依赖复制到目标目录(技能包 _run/)。 * 仅复制与 sb 绑定相关的固定文件名/目录,避免带入历史临时脚本。 */ private copyRuntimeDeps; private copyDir; destroy(): Promise; } //# sourceMappingURL=local-sandbox.d.ts.map