sebaxzero/pi-browser-search
GitHub: sebaxzero/pi-browser-search
为 pi AI 助手提供基于真实 Playwright 浏览器的网页搜索与交互能力,并内置提示注入净化与 SSRF 防护的安全扩展。
Stars: 0 | Forks: 0
# pi-browser-search
[](https://github.com/sebaxzero/pi-browser-search/actions/workflows/test.yml)
[](https://www.npmjs.com/package/pi-browser_search)
一个 [pi](https://pi.dev) 扩展,添加了由真实 Playwright Chromium 浏览器支持的 `browser_search`、`browser_open`、`browser_act` 和 `browser_read` 工具。
静态抓取无法处理 JavaScript 渲染的页面、SPA、Cookie 墙或懒加载内容。此扩展转而驱动真实的浏览器,同时强制执行与 [pi-safe-search](https://github.com/sebaxzero/pi-safe-search) 相同的纵深防御:对每个结果进行提示注入净化,并在网络层对浏览器发出的每个请求(不仅仅是模型请求的请求)强制执行 SSRF 保护。
## 安装
从 npm 安装:
```
pi install npm:pi-browser-search
```
或从 git 安装:
```
pi install git:github.com/sebaxzero/pi-browser-search.git
```
在任一形式后添加 `-l` 以在项目本地安装(仅添加到 `.pi/settings.json`)。
无需手动设置:`playwright` npm 依赖会随包自动安装,Chromium 二进制文件(约 150 MB)会在首次启动浏览器时下载一次。如果想预先下载,可以在安装目录中运行 `npx playwright install chromium`。
## 工作原理
### 净化流水线(在每个结果上运行)
与 pi-safe-search 共享。每一段页面内容在到达 LLM 之前都会经过此流水线:
1. **Unicode 标准化** — NFKC 标准化加上同形异义字符映射,将相似字符折叠为 ASCII
2. **零宽字符移除** — 剔除用于隐藏指令的不可见字符
3. **控制字符剔除** — 移除空格以下的所有字符,除了 `\t`、`\n`、`\r`
4. **HTML 实体解码 → 重新剔除** — 解码 `<script>`,然后剔除生成的标签
5. **URL 解码** — 捕获百分号编码的 payload
6. **Base64 块脱敏** — 将可疑的 base64 块替换为 `[BASE64_ENCODED_DATA]`
7. **注入模式脱敏** — 覆盖指令、角色劫持、系统 prompt 提取、模式切换等
8. **随机分隔符包裹** — 内容使用随机 token 进行围栏处理,以便 LLM 将其中的所有内容视为数据,而不是指令
第二次净化过程通过 `tool_result` hook 在每个工具结果上运行,捕获任何漏网之鱼。
### 网络层的 SSRF 保护
与普通的基于 fetch 的工具不同,渲染后的页面可以发出模型从未请求过的请求——重定向、iframe、XHR 调用、子资源。`context.route("**/*")` 拦截器会针对以下内容检查**每一个**请求:
- 非 http(s) 协议(`file://`、`ftp://` 等)
- 危险端口:21、22、25、53、3306、5432、6379 等
- RFC-1918、环回、链路本地和保留的 IP 范围(DNS 解析,60 秒缓存)
`browser_open` 还会在导航开始前预先验证 URL,并给出描述性错误。
### 浏览模型
该扩展维护一个延迟启动的浏览器/上下文以及一个“当前页面”。`browser_open` 导航并提取文本和链接;`browser_act` 在该页面上点击、输入、按键、滚动或等待;`browser_read` 通过字符偏移量分页浏览最后提取的内容,而无需重新抓取。打开新标签页的点击会自动切换到该标签页,对话框会自动关闭。
`browser_search` 有意在普通的 fetch 上使用 DuckDuckGo 的静态 HTML 端点 —— DDG 会屏蔽 headless Chromium —— 因此浏览器只花在需要它的地方:渲染页面并与之交互。
## 工具
**`browser_search`** — 搜索 DuckDuckGo 并返回标题、URL 和摘要。
参数:
- `query`(必填)— 搜索查询
- `max_results`(可选)— 结果数量,默认为 5,最大为 10
**`browser_open`** — 导航到 URL 并返回渲染后的文本以及链接列表。
参数:
- `url`(必填)— 必须为 http 或 https
**`browser_act`** — 与当前打开的页面进行交互:click、type、press、scroll 或 wait_for。
**`browser_read`** — 通过字符偏移量分页浏览最后快照中提取的文本,无需重新抓取。
## 配置
持久配置存在于 `extensions/browser-search.json` 中(首次加载时自动创建并使用默认值)。你可以直接要求 agent 编辑它:
```
{
"MAX_RESULTS": 5,
"MAX_CHARS": 8000,
"MAX_LINKS": 25,
"NAV_TIMEOUT_MS": 30000,
"HEADLESS": true,
"BLOCK_MEDIA": true
}
```
| 键 | 默认值 | 描述 |
|-----|---------|-------------|
| `MAX_RESULTS` | `5` | `browser_search` 返回的默认搜索结果数 (1–10) |
| `MAX_CHARS` | `8000` | 每次 `browser_read` 分块返回的页面文本 |
| `MAX_LINKS` | `25` | 每页列出的链接数 |
| `NAV_TIMEOUT_MS` | `30000` | 导航超时(以毫秒为单位) |
| `HEADLESS` | `true` | 设置为 `false` 以监视浏览器窗口 |
| `BLOCK_MEDIA` | `true` | 跳过加载图像/媒体/字体 |
更改 `HEADLESS` 或 `BLOCK_MEDIA` 或 `NAV_TIMEOUT_MS` 会关闭当前浏览器,以便下一次调用时使用新选项重新启动。
对 JSON 的更改将在下一次会话中生效。要在会话中进行实时调整,请使用以下命令。
## 命令
```
/browser-search — show current status and config
/browser-search set KEY=VAL — override config for the current session only
/browser-search reset — close the browser
```
## 兼容性
与 [pi-safe-search](https://github.com/sebaxzero/pi-safe-search) 共享其净化和 SSRF 模型 —— 如果你希望对大多数页面使用廉价的静态抓取,而将真实浏览器留给重度依赖 JS 的页面,请同时安装两者。
## 依赖项
`playwright` (^1.53.0) —— 随包自动安装,无论是通过 `pi install npm:` 还是基于 git 的安装。Chromium 二进制文件将在首次启动浏览器时单独下载(参见上文的安装说明)。
## 测试
```
node --test test.mjs
```
17 个测试,涵盖 IP 范围检查、URL 验证、DuckDuckGo 重定向
解包以及净化冒烟测试。纯逻辑存在于 `net.ts` 和
`sanitize.ts` 中(无 Playwright 导入),因此测试套件无需浏览器即可运行。
CI 会在每次推送和拉取请求时运行它。
## 发布
更新 `package.json` 中的 `version`,提交,打上 `vX.Y.Z` 标签,并推送该标签 ——
发布工作流将运行测试并发布到 npm。
## 许可证
MIT
使用 [Claude](https://claude.ai) 构建。
标签:AI工具集成, MITM代理, Playwright, SSRF防护, 提示词注入防御, 暗色界面, 特征检测, 自动化攻击, 自动化浏览器