Forge 开发笔记 08:给 Agent 画边界

Posted on Jun 27, 2026

一个能读文件、改文件、跑命令的 Agent,天然需要边界。

如果 Agent 只能聊天,风险主要在内容层面;一旦它能执行本地命令,风险就进入了系统层面。它可能误删文件,访问不该访问的路径,运行长时间卡死的命令,或者尝试联网下载东西。即使模型没有恶意,错误的工具调用也可能造成真实副作用。

Forge 的 v0.7 引入 Sandbox 和执行限制,就是为了把这个问题摆到台面上。

源码版本:arjenzhou/forge@3be6fb9,对应 v0.7.0-sandbox

设计思路:工具能力必须被授权

Agent 能调用工具,不代表它应该默认拥有无限权限。尤其是 run_command 这种工具,既能跑测试,也能删除文件、挂起进程、访问网络。系统必须把“模型请求行动”和“系统批准行动”分开。

Forge v0.7 的目标不是做生产级隔离,而是把最小边界放进执行路径:路径必须在 workspace 内,命令要经过危险模式过滤,子进程要有 timeout,工具执行时由系统注入 sandbox。

这个设计的重点是:边界不是 prompt 里的建议,而是工具执行层的规则。

代码落点

对应源码:

examples/demo_sandbox.py  # 危险命令、网络请求、超时命令
forge/sandbox.py          # LocalRestrictedSandbox
forge/tools.py            # 工具通过 sandbox 执行
forge/runner.py           # runner 注入 sandbox

这不是 hardened sandbox

先说清楚:Forge 的 sandbox 不是生产级安全沙箱,也不是用来运行不可信代码的 OS 级隔离环境。

源码自己也这么写:

class LocalRestrictedSandbox(BaseSandbox):
    """A local execution boundary for path checks, timeouts, and shell-free commands.

    This is not an OS security sandbox. Commands still run as the current user,
    so untrusted code requires a real container or process isolation layer.
    """

它更准确的名字,是 local execution boundary。它用一些简单机制限制危险动作:

  • workspace path checks;
  • 命令关键字过滤;
  • 子进程 timeout;
  • shell-free command execution;
  • 工具层依赖注入 sandbox。

路径边界

Coding Agent 最基本的边界是 workspace。

Forge 用 _validate_path() 防止工具访问 workspace 外部:

def _validate_path(self, filepath):
    target_path = os.path.abspath(os.path.join(self.workspace_dir, filepath))
    if os.path.commonpath([self.workspace_dir, target_path]) != self.workspace_dir:
        raise SecurityViolationError(
            f"Directory Traversal Denied: Path '{filepath}' is outside sandbox"
        )
    return target_path

read_file()write_file() 都先过这个检查:

def read_file(self, filepath):
    target_path = self._validate_path(filepath)
    with open(target_path, "r", encoding="utf-8") as f:
        return f.read()

模型可以请求读某个路径,但 sandbox 负责判断这个请求是否合法。

命令边界

run_command 是 Coding Agent 最有用、也最危险的工具之一。

Forge v0.7 在 LocalRestrictedSandbox 里加了 blocklist 和 timeout:

self.blocked_patterns = [
    r"\brm\s+-[rf]+\b",
    r"\bsudo\b",
    r"\bchown\b",
    r"\bchmod\b",
    r"\bcurl\b",
    r"\bwget\b",
    r"\bsh\b",
    r"/etc/passwd",
]

执行命令前先扫一遍:

for pattern in self.blocked_patterns:
    if re.search(pattern, command):
        return f"[Security Error] Execution Blocked: Command contains dangerous pattern '{pattern}'."

argv = shlex.split(command)
res = subprocess.run(
    argv,
    cwd=self.workspace_dir,
    capture_output=True,
    text=True,
    timeout=timeout_seconds
)

这里还有两个细节:不用 shell,先 shlex.split();命令在 workspace 里运行,并设置 timeout。

工具如何拿到 sandbox

模型看到的 run_command 参数只有 command,但真实函数签名里还有隐藏参数:

def run_command(command: str, sandbox: Optional[BaseSandbox] = None) -> str:
    if sandbox:
        return sandbox.execute_command(command, timeout_seconds=10)

ToolRegistry.register() 生成 schema 时会跳过 sandbox

if param_name in ("self", "cls", "sandbox", "runner"):
    continue

执行时,runner 再把 sandbox 注入进去:

result = self.tool_registry.execute(
    func_name,
    args,
    sandbox=self.sandbox,
    runner=self
)

这让 LLM 看到的是“可调用工具”,系统内部看到的是“带执行策略的工具”。

Demo 里发生了什么

运行:

python examples/demo_sandbox.py

前几轮 MockModel 会故意尝试危险动作:

[Runner] Requesting Tool (Sequential): run_command
args: {"command": "rm -rf /some/dangerous/path"}
[Tool Output]: [Security Error] Execution Blocked: Command contains dangerous pattern '\brm\s+-[rf]+\b'.

接着尝试 curl

args: {"command": "curl -s http://example.com/asset.zip"}
[Tool Output]: [Security Error] Execution Blocked: Command contains dangerous pattern '\bcurl\b'.

再尝试一个睡 15 秒的命令:

args: {"command": "python -c \"import time; time.sleep(15)\""}
[Tool Output]: [Timeout Error] Command exceeded execution limit of 10 seconds and was forcefully terminated.

这些都被系统拒绝后,Agent 才回到真正任务上:读 calculator.py,修复 divide-by-zero,再跑测试。

边界不是不信任,是协作前提

给 Agent 画边界,不是因为假设它一定会作恶,而是因为任何自动执行系统都应该有边界。

人类开发者也有边界:权限、代码评审、CI、测试环境、生产审批。Agent 只是把行动速度提高了,所以边界更不能省。

Forge 的 sandbox 很轻,但它明确表达了一个心智:Agent 的能力应该被授权,而不是默认无限。

如果把这套思路扩展到生产系统,就会走向更强的隔离:独立系统用户、容器或虚拟机、网络隔离、allowlist、用户确认、高风险工具分级。Forge 没有一次性做完这些,但它把最小边界放进了执行路径。

Comments: