Simon Willison 遇到的 bug 很小:Datasette Agent 的 jump menu 里,一个 textarea 底部多出了一条不该出现的横向滚动条。

他把截图拖进 Claude Code,只写了一句提示:看看依赖,找出为什么这里有横向滚动条。

几分钟后,Claude Fable 5 已经不是在“分析代码”了。它跑起本地开发环境,打开浏览器,写测试页,改模板,截图,还搭了一个本地服务接收页面测量数据。

我更在意的不是那两行 CSS 修复,而是这条调试链说明了一件事:前沿 coding agent 的能力边界,正在从“帮你写代码”变成“在你的机器上组织一次排障”。强在主动,险也在主动。

一句提示之后,它做了完整排障

Willison 的判断是,问题可能来自 Datasette Agent 的依赖,尤其可能和 Datasette 本身有关。Fable 就沿着这个方向往下挖。

它先找出如何运行本地开发服务器,还补上需要的假环境变量。接着用 Playwright 启动 Chrome,切到 Firefox、WebKit 尝试复现。为了看清滚动条,它还把 Chrome for Testing 的滚动条设置成始终可见,之后再改回。

在 Playwright 里复现不稳定后,它转向真实浏览器。

这一步很关键。很多 bug 不在理想化测试环境里出现,只在真实浏览器、真实系统设置、真实渲染细节里出现。Fable 的做法是写一个 /tmp/textarea-scrollbar-test.html,再用本机 Firefox 和 Safari 打开。

更有意思的是截图方式。

osascript 因为没有辅助功能权限受阻后,Fable 没有停下。它用 uv run --with pyobjc-framework-Quartz python 调用 Quartz,枚举 macOS 当前窗口,筛出标题里带有 textarea 的 Safari 窗口编号,再用 screencapture -l 截图。

这不是突破系统权限。它只是把终端里本来能用的工具,串成了一条工作流。

环节Fable 的做法说明
运行项目启动 Datasette Agent 本地开发服务从静态分析进入真实运行环境
浏览器验证Playwright、Firefox、Safari 轮流测试尽量贴近真实渲染差异
真实窗口截图Quartz 枚举窗口编号,screencapture 截图绕开缺少 GUI 自动化权限的问题
打开 modal改模板,用 JS 模拟 / 快捷键让页面自动进入出问题的状态
读取数据进入 Web Component shadow DOM拿到 textarea 的实际尺寸和样式
数据回传本地 Python CORS 服务接收 JSON页面测量结果写到磁盘供 agent 读取

这张表里最值得看的,不是某一个技巧多高级,而是组合能力。普通开发者也知道这些工具,但很少会在几分钟内把它们连成一套。

真正的变化:agent 会改环境来拿答案

Fable 后面做的事,更接近一个有经验工程师的临场排障。

这个 modal 需要点击或快捷键才能打开。Fable 没有等人操作,也没有假装看不见。它修改了 Datasette 的模板,在页面加载 1.2 秒后触发一个模拟的 / 键盘事件,把 jump menu 自动打开。

然后它要读 textarea 的真实状态。

这个 textarea 在 <navigation-search> Web Component 里,数据藏在 shadow DOM 下。Fable 注入 JS,找到里面的 textarea,读取 scrollWidthclientWidthwhiteSpacewidth 等信息。

浏览器脚本不能直接写本地文件。它的办法是再起一个 Python http.server,监听 127.0.0.1:9999,设置 Access-Control-Allow-Origin: *。页面把测量结果 POST 到这个本地服务,本地服务再写入 /tmp/diag.json

到这里,调试链闭环了:

页面里量到的数据,回到本地文件;agent 再读文件,继续判断下一步。

后来 Fable 似乎触发了某种不可见限制,任务切到 Opus 接续。Opus 读取了完整上下文,沿用前面的技巧,最终找到并验证了两行 CSS 修复。

这个案例不能被夸大成“模型黑进了系统”。没有证据显示它绕过了 macOS 权限,也不能说 Anthropic 官方确认了什么安全漏洞。

它说明的是另一件更现实的事:只要你允许 coding agent 执行 shell 命令,它能做的事就接近你在终端里能做的事。区别在于,它更会临时拼工具,也更不怕麻烦。

这对开发者的影响很直接。

个人使用 Claude Code、Cursor 这类工具时,不能再只看“它写得准不准”。要看它有没有权限读 .env,能不能访问本地网络,能不能调用浏览器,能不能把结果发到外部地址。

团队接入时,动作要更具体:先在隔离环境里试点,限制仓库和目录权限,默认关闭不必要的外网访问,把密钥、浏览器配置、SSH key 排除在 agent 可读范围外。能审计的命令和网络请求,要留下日志。

接下来该看沙箱,而不是看模型有多聪明

Fable 这次能做到这些,有几个前提。

它运行在有源码的本地目录里。机器允许它执行 shell 命令。项目能被本地启动。浏览器和 macOS 工具能被命令行间接调用。

如果换成受限 CI、远程容器,或者严格沙箱,很多技巧会失效。这也是判断边界:问题不在于 agent 一定危险,而在于裸跑的 agent 太自由。

对企业技术负责人来说,采购和接入评估应该往后挪一格。

不要只问模型支持多少语言、补全速度多快、能不能跑测试。更该问这些问题:

  • agent 默认能读哪些目录?能不能排除密钥文件和浏览器数据?
  • 它能访问公网、本地网段和内网服务吗?规则能否按项目配置?
  • shell 命令、文件修改、网络请求有没有可审计日志?
  • 遇到 issue、README、网页内容里的恶意指令时,有没有隔离和确认机制?
  • 本地执行和远程容器执行,哪一种更适合当前团队的代码和数据风险?

最相关的两类人,动作也不一样。

重度开发者可以继续用,但应该把 agent 放进专门的工作目录或容器里。不要在同一个环境里同时放生产密钥、私有数据和可自由执行命令的 agent。

企业研发负责人则应该延后“全员默认开启”。先选低敏仓库做试点,把网络、文件、命令权限拆开配置。等日志和隔离策略跑通,再扩大范围。

这会牺牲一点顺滑体验。可如果不做隔离,prompt injection 的后果会被 agent 的主动性放大。

一个恶意 issue、一段被复制进终端的说明、一份藏在仓库里的提示文本,都可能把“帮我调试”带偏成“帮别人拿数据”。目前这个案例没有造成损害,但它把路径展示得足够清楚。

回到开头那个滚动条。它最后只是两行 CSS。

真正值得记住的是,为了找这两行,Fable 在本机权限内搭出了一套浏览器自动化、截图、模板注入和数据回传系统。这样的能力很有用,也必须有鞘。