Hotdry.
security

用 Fence 实现无容器 CLI 沙箱:网络与文件系统权限控制

面向半可信 CLI 命令(包安装、构建脚本、AI 代理),给出 Fence 的无容器沙箱架构与网络/文件系统权限控制的工程化配置参数。

在日常开发中,我们经常需要运行来自外部的半可信代码:安装不知来源的 npm 包、执行不熟悉的仓库构建脚本、或者让 AI 编码代理在受限环境中操作。传统的解决方案是启动完整的容器,但这带来了显著的资源开销和运维复杂度。Fence 提供了一种轻量级的替代方案 —— 无需容器即可对 CLI 命令进行网络隔离和文件系统访问控制,特别适合作为深度防御手段集成到 CI/CD 流水线或 AI 代理工作流中。

核心设计理念:无容器沙箱

Fence 的核心思路是使用操作系统原生的沙箱机制,而非完整的容器运行时。在 Linux 平台上,它依赖 bubblewrap 来创建轻量级的命名空间隔离;在 macOS 上则使用 sandbox-exec。这使得 Fence 能够在不引入 Docker 等容器基础设施的情况下,实现进程级别的资源隔离。默认配置下,所有网络出口被阻断,文件系统访问受到严格限制,危险命令(如 rm -rf /git push)会被直接拦截。这种设计让用户可以放心地运行那些 "不太确定是否安全" 的命令,而不必担心它们会对系统造成实质性破坏。

Fence 的配置模型采用 JSON 格式,默认读取用户主目录下的 .fence.json 文件。一个典型的配置文件结构包含四个主要维度:网络规则、文件系统规则、命令过滤规则以及模板继承关系。网络规则支持域名白名单,允许指定哪些域名可以在沙箱内被访问;文件系统规则控制读写路径的允许范围;命令过滤规则则提供基于正则表达式或精确匹配的禁止命令列表。这种声明式的配置方式使得安全策略可以被版本控制、审计和自动化分发。

工程化配置参数详解

在实际部署中,合理的参数配置是发挥 Fence 安全效能的关键。以下是一个针对代码开发场景的参考配置,它在限制权限的同时保留了必要的功能:

{
  "extends": "code",
  "network": {
    "allowedDomains": ["registry.npmjs.org", "pypi.org", "*.company-internal.com"]
  },
  "filesystem": {
    "allowWrite": ["/tmp/fence-workspace", "$HOME/code/.cache"]
  },
  "command": {
    "deny": ["rm -rf /", "git push", "npm publish", "docker run"]
  }
}

这个配置做了几项重要的工程决策。首先,它继承了内置的 code 模板,该模板已经为常见的开发工具(npm、pip、git 等)预置了合理的默认规则,避免了从零开始配置的繁琐。其次,网络白名单明确限定了包管理器的域名和公司内部域名,其他所有网络请求将被拒绝 —— 这意味着即使恶意代码试图外发数据或下载后门程序,也会因为无法解析域名而失败。文件系统写入限制确保了沙箱内产生的数据只会落到特定目录,不会污染用户的 home 目录或系统关键路径。命令过滤则直接阻止了可能造成不可逆损害的操作,即使攻击者获得了命令执行权限,也无法执行这些高危操作。

对于需要更高隔离级别的场景(如运行来源不明的脚本),可以进一步收紧参数:将 allowedDomains 设为空数组以完全阻断网络,将 allowWrite 限制为只读挂载点,并添加更严格的命令过滤规则。Fence 的 -m 标志支持监控模式,会使用 bpftrace 实时记录所有被拦截的系统调用和文件系统操作,这在安全审计和策略调优阶段非常有用。

架构实现与监控机制

从实现角度看,Fence 的安全模型建立在多层防御之上。最外层是 bubblewrap 提供的进程命名空间和挂载命名空间,它确保沙箱内的进程无法看到宿主的进程列表,也无法访问未显式挂载的目录。中间层是 Fence 自己实现的网络过滤逻辑,通过 socat 进行网络流量的转发和检查,只有符合配置白名单的域名才会被放行。最内层是命令级别的过滤,它在命令实际执行之前进行检查,避免了通过 shell 逃逸或参数混淆绕过限制的可能性。

监控与可观测性是生产环境部署不可或缺的一环。Fence 的 -m 选项会启动 bpftrace 探针,追踪所有尝试访问受限资源的系统调用,并以结构化日志的形式输出。这些日志可以接入企业的 SIEM 系统或日志聚合平台,实现对沙箱行为的持续监控。当检测到异常的访问模式(如短时间内大量被拒绝的文件读取尝试)时,可以触发告警或自动化的响应流程。值得注意的是,bpftrace 的开销相对较低,在大多数现代服务器上对命令执行性能的影响可以忽略不计。

典型应用场景与边界条件

Fence 的设计定位决定了它最适合以下几类场景。第一类是 CI/CD 流水线中的依赖安装步骤,特别是在使用第三方构建脚本或未知来源的包时,可以在不显著增加流水线时间的前提下降低供应链攻击的风险。第二类是 AI 编码代理的安全防护,通过为 Claude、Cursor 等 AI 工具配置受限的沙箱环境,既能保持代码生成的能力,又能防止 AI 意外执行危险操作或访问敏感文件。第三类是临时性的代码审查或漏洞复现环境,研究人员可以在沙箱内安全地运行不信任的代码片段,而不必担心影响宿主机。

然而,Fence 并不是银弹,它有其固有的边界条件。首先,bubblewrap 需要 root 权限或适当的 capabilities 配置,这意味着在某些受限环境中可能无法使用。其次,对于需要图形界面或复杂系统调用的应用,纯粹的命名空间隔离可能不够,这类场景仍需要完整的容器或虚拟机隔离。此外,Fence 的安全性依赖于配置的正确性,错误的白名单设置可能会引入意外的访问路径,因此生产环境中的配置变更应当经过严格的代码审查。

资料来源:Fence 官方 GitHub 仓库(github.com/Use-Tusk/fence)。

查看归档