Playwright 浏览器安全:测试用 Chromium 别拿来上网

装过 Playwright 的机器上,通常躺着几个你没主动装的浏览器:npx playwright install 下载的 Chromium(1.57 起是 Chrome for Testing 构建)、Firefox 和 WebKit。它们是给自动化测试准备的,版本跟着 Playwright 走,启动时默认不开 Chromium 沙箱。拿它跑自己的测试没问题,让 Agent 用它去打开陌生网页,就是另一回事了。下面按 Playwright 官方文档、Playwright MCP 的 README 和 playwright-core 1.64.1 源码(2026-11-04 北京时间查阅),讲清两类用法的安全差别和该怎么配。
测试浏览器和日常浏览器,设计目标不同
官方文档开头就写了:每个 Playwright 版本需要特定版本的浏览器二进制,要用 Playwright CLI 安装。它们装在系统缓存目录里,Linux 是 ~/.cache/ms-playwright,macOS 是 ~/Library/Caches/ms-playwright,Windows 是 %USERPROFILE%\AppData\Local\ms-playwright,每个几百 MB。
这些浏览器不走 Chrome 那套自动更新。你一年没升级 Playwright,缓存里的 Chromium 就是一年前的版本,这期间 Chrome 修过的漏洞它都没有。官方给的办法是定期升级 Playwright 再重装浏览器。
| 对比项 | Playwright 测试浏览器 | 本机 Chrome / Edge 正式版 |
|---|---|---|
| 来源 | npx playwright install 下载 | 自己安装的品牌浏览器 |
| 更新 | 跟 Playwright 版本走,不自动更新 | 浏览器自动更新 |
| launch() 默认沙箱 | 关(chromiumSandbox 默认 false) | 同样默认 false,要自己打开 |
| Playwright MCP 默认 | Linux 上 --browser chromium 时沙箱关 | 默认用 chrome 通道,沙箱开 |
| 适合 | 跑自己应用的测试 | 让 Agent 访问外部网页 |
脚本里的写法:换通道,开沙箱
自己写 Playwright 脚本让 Agent 访问不受信任的页面,至少改两处:用本机已更新的 Chrome,显式打开沙箱。
const { chromium } = require('playwright');
const browser = await chromium.launch({
channel: 'chrome', // 用本机 Chrome 正式版,也可以是 'msedge'
chromiumSandbox: true, // 默认是 false,要手动打开
});
channel 可选值在 API 文档里列全了:chrome、chrome-beta、chrome-dev、chrome-canary,以及对应的四个 msedge 通道。测试配置文件里同样能按项目写 channel: 'chrome'。
测试浏览器访问的是你自己的应用,Agent 打开的却可能是任何网页,两种场景的默认配置不该一样。
Playwright MCP 默认做了什么
给 Claude Code、Cursor 接的 Playwright MCP(@playwright/mcp)比裸用 API 稳妥一些。读 playwright-core 1.64.1 里 MCP 的配置校验代码可以看到:
- 没指定浏览器时,用 Chromium 内核并把通道设成
chrome,也就是本机装的 Chrome 正式版。 - 没显式设置沙箱时,macOS 和 Windows 一律打开;Linux 上只有通道是
chromium或chrome-for-testing时才关。 - 命令行传
--browser chromium,会被映射成chrome-for-testing通道。
所以在 Linux 上为了省事写了 --browser chromium,沙箱就默认关了。需要的话加 --sandbox 强制打开。README 里的 Docker 示例用的是 --no-sandbox,那是容器场景的写法,别照抄到本机配置里。
不是安全边界,就别当边界用
Playwright MCP 的 README 有一句写得很直白:Playwright MCP 不是安全边界。--allowed-origins、--blocked-origins 两个参数的说明也注明不构成安全边界,而且不影响重定向。它们适合减少误访问,挡不住恶意页面。
另一个默认值也要留意:Playwright MCP 默认像普通浏览器一样用持久化配置,位置在 ~/.cache/ms-playwright/mcp-{channel}-{workspace-hash}(macOS 在 ~/Library/Caches 下)。Agent 在里面登录过的网站,cookie 会一直留着。处理陌生网页时加 --isolated,配置只放内存,关浏览器就清掉。这一点和站内讲过的 Chrome DevTools MCP 一样,要先想清楚 Agent 能碰到哪些登录态。
两种更危险的接法
README 里还有两种接法,安全风险更高。
第一种是 --extension:装上 Playwright 的 Chrome 扩展后,MCP 直接连到你正在用的 Chrome 或 Edge,README 原话是可以「利用你已登录的会话和浏览器状态」。这样 Agent 拿到的是你日常的浏览器,里面有邮箱、网银、公司后台的登录态。适合需要真实登录态的少数任务,用完就断开,别长期挂着。
第二种是 Docker 示例:--headless --browser chromium --no-sandbox --port 8931 --host 0.0.0.0。沙箱关了,端口监听在所有网卡上。容器里跑可以接受,前提是这个端口不对公网开放;本机直接这样启动,端口只要能被别的机器访问到,对方就能连上来控制这个浏览器。自己用的话,--host 保持本机回环地址就够了。
测试项目本身倒不用改太多。playwright.config 里按项目写 channel: 'chrome' 就能用本机 Chrome 跑,只在 CI 上无头跑测试的话,安装时加 --only-shell,只装无头 shell,不下完整浏览器。
清理和升级
# 看本机所有 Playwright 装过的浏览器、版本和位置
npx playwright install --list
# 升级 Playwright 再装新浏览器
npm install -D @playwright/test@latest
npx playwright install
# 删掉当前安装的浏览器 / 删掉所有 Playwright 装过的浏览器
npx playwright uninstall
npx playwright uninstall --all
官方文档说,Playwright 会记录哪些包需要哪些浏览器,升级时自动清掉不再用的旧版本。装过多个项目的机器上,不同版本可能同时存在,跑一遍 --list 就清楚了。
常见坑
- 把测试浏览器当日常浏览器。它不自动更新,默认不开沙箱,不适合打开陌生网页、登录个人账号。
- 以为白名单能挡住攻击。官方文档写明 origin 白名单不是安全边界,重定向也不受它管。
- 照抄 Docker 示例的参数。
--no-sandbox和--host 0.0.0.0是给容器准备的,写进本机的 MCP 配置就是同时关掉沙箱、敞开端口。 - 持久化配置留着登录态。多个 Agent 共用一个工作区还会冲突,README 建议并行时用
--isolated或分开的--user-data-dir。
完成标准
npx playwright install --list里没有你不认识的旧版本浏览器。- 访问外部网页的脚本和 MCP 配置,用的是
chrome/msedge通道,沙箱是开的。 - 处理陌生网页的 Agent 会话跑在
--isolated模式,或单独的用户数据目录里。
最后
现在就在自己机器上跑一次 npx playwright install --list,再翻一下 MCP 配置里有没有写 --browser chromium 或 --no-sandbox。想顺手查一遍 Agent 装了哪些插件和 MCP,看本站的 Agent 插件自查教程。