所有页面
本页内容

OAR 暴露什么、不暴露什么

本页把 OAR 暴露什么、不暴露什么集中在一处。每条事实都另有其所属页面,每一节末尾都附有指向该页面的链接。简而言之:中继以你的身份行事,访问令牌意味着对它的完全控制,而你创建的少数几种链接是有意公开的。

信任模型 #

中继以一个操作系统用户身份运行,它的智能体也以该用户、以该用户的权限运行。你在机器上能做的任何事,都可以要求智能体去做。没有任何东西限制智能体的 shell。智能体可以读取配置文件(连同其中的访问令牌)、数据库(连同提供商密钥和已配对中继的令牌)以及提供商的登录文件。访问令牌赋予对中继的完全控制,从而也赋予对智能体所能做之事的完全控制:持有它的人可以让智能体在主机上运行命令。OAR 扩大了这些智能体能触及的范围,但没有增加任何沙箱。

唯一的例外是 Claude Cloud,它的智能体在 Anthropic 的一个沙箱中对 GitHub 仓库的克隆进行工作,而不是在你的机器上(参见什么会离开你的机器)。

智能体可以触及什么 #

工作目录是智能体工作的地方。它并不是一堵墙。以下是 OAR 强制执行的,以及它不强制执行的:

OAR 强制执行的 OAR 不强制执行的
workspaceRootAllowList 限制可以在哪些文件夹中启动对话,以及可以用 Change CWD(更改工作目录)把对话移到哪些文件夹。未设置时,任何已存在的文件夹都被允许。 没有任何东西把智能体的 shell 限制在工作目录内。它可以在中继用户能读写的地方读写。
中继模式告诉智能体可以多自由地行事。有些提供商会强制执行其中一部分:GitHub Copilot 和 OpenAI 的 SDK 引擎在 plan 模式下拒绝任何非只读的操作,在 ask 模式下会先问你。 Claude 以及 0.9.17 新增 DeepSeek 在所有模式下运行每个工具都不询问你。Grok 的权限请求全部被批准。在扩展引擎上,OAR 不检查任何权限。那里的模式只是智能体遵循的一条指令。
静态预览只能提供工作目录内的一个文件夹。 允许列表不检查 Default(默认)文件夹,也不限制你能浏览什么。

详情:限制对话可以从哪里开始、中继模式和智能体与令牌。

无需登录即可访问的内容 #

凡是读取或更改你的对话、文件、设置或智能体的操作都需要访问令牌。以下是例外情况:

内容 它暴露什么 如何关闭它
登录页面和静态应用 网页应用及其登录框。它不保存你的任何数据。 无法关闭。让中继远离互联网(localhostOnly),或在前面设置访问规则。
分享链接(/shared/…) 对话的对话记录,只读,并显示每条消息所用的模型。中继主机的路径会被过滤(默认只显示文件名),你隐藏的消息不会被发送。每次打开都会被记录。 在 Settings → Sharing(设置 → 分享)中点击 Stop sharing(停止分享)或 Renew link(更新链接),或删除该对话。之后旧地址只会返回普通的 404。链接永不过期。
预览链接 被预览的开发服务器或文件夹。链接的随机令牌是它唯一的保护。 Close(关闭)预览,或 /preview close。预览通道在你配置之前一直关闭。预览在中继重启后仍然存在,并在你关闭它或删除其对话时结束。

中继前面的 Cloudflare Access 应用也会拦截分享链接的查看者,除非放行 /shared/* 和 /api/shared/*——这会有意让这两条路径公开(Cloudflare Access)。

详情:你的分享链接、查看者看到什么、预览和什么需要令牌。

已登录的浏览器能访问什么 #

持有令牌的浏览器可以打开中继上的每个对话,也能使用文件浏览器。在 Linux 和 macOS 上,驱动器根目录会提供中继用户可读的任何文件,无论是否在工作目录内。重命名和删除作用于该用户可写的任何位置,而且删除不会进入回收站。在 Windows 上,浏览器被限制在中继列出的驱动器内。显示智能体图片的媒体路由以同样方式工作:它提供中继用户可读的任何绝对路径,但只对携带令牌的请求提供。

详情:文件浏览器、图片与媒体。

机密 #

机密 它存放在哪里
访问令牌 config.json,以纯文本存放。中继让该文件仅限所有者访问。浏览器也以登录 cookie 的形式持有它。
Cloudflare 隧道令牌 config.json(cloudflaredTunnel.token)或环境变量。
OpenAI、Cursor、0.9.17 新增 DeepSeek 和 0.9.18 新增 Claude API 密钥 数据库。它们绝不会被发送给浏览器。每个密钥只交给其自身提供商的 worker;DeepSeek 密钥离开本机时只发往 DeepSeek 基础 URL,Claude API 密钥只发往 https://api.anthropic.com。
已配对中继的令牌 数据库。它绝不会被发送给浏览器或智能体。
分享链接令牌、推送密钥 数据库。
Claude、Grok 和 GitHub Copilot 的登录 各提供商自己在本机上的文件夹(~/.claude、~/.grok、Copilot CLI 的登录)。OAR 不保存其中任何一个。DeepSeek 对话不使用其中任何一个。0.9.18 新增 Claude API 对话共用 Claude 文件夹,但使用已保存的密钥运行,而不是登录。
中继环境中的 Claude 登录令牌(CLAUDE_CODE_OAUTH_TOKEN) 0.9.17 新增 在所有平台上只交给 Claude 和 Claude Cloud worker。此前,其他 worker 也可能拿到它。
中继环境中的 Anthropic 密钥或令牌(ANTHROPIC_API_KEY、ANTHROPIC_AUTH_TOKEN) 0.9.17 新增 不交给任何 worker。此前,每个 worker 都会拿到它,Claude 对话会用它运行,而不是用 Claude 登录。0.9.18 新增 以订阅方式运行、启动后却用上了 Claude Code 自身设置中某个 API 密钥的 Claude 对话,也会被停止;参见 Claude。

智能体以与中继相同的用户运行。因此“仅所有者”的文件模式并不能把智能体挡在外面:它可以读取 config.json、数据库和提供商文件夹。OAR 中没有任何东西对智能体隐藏它们。中继自己的 worker 以及智能体用来访问中继的工具从 config.json 读取访问令牌。relay_tool 绝不会把另一个中继的令牌交给智能体:调用会经过你的中继,由它加上令牌。但智能体仍可能从数据库读取那个令牌。数据库的备份含有上述密钥和令牌,因此要像状态文件夹一样妥善保密。

0.9.17 新增 DeepSeek 对话的智能体可以从其环境读取 DeepSeek 密钥。会话 worker 发来的任何内容,中继在存储或显示之前都会把其中的密钥替换为 [redacted],从而让它不出现在对话记录中,但这挡不住一个想要拿到该密钥的智能体。参见密钥保存在哪里。

0.9.18 新增 Claude API 对话中的 Claude API 密钥同样如此。该对话共享你的 Claude 登录所在的 Claude 文件夹,因此中继会用已保存的密钥覆盖其设置中的任何凭据,并停止 Claude Code 报告其密钥另有来源的那一轮。Claude Code 会在该报告之后片刻发出它的第一个模型请求,因此在停止之前,可能已经有一个模型请求用另一个凭据发出:这项检查把错误凭据的影响限制在这一个模型请求上,但并不能阻止它。参见 Claude API → 安全。

0.9.18 新增 DeepSeek 和 Claude API 对话使用中继持有的密钥运行,在这些对话中,Claude Code 启动时会关闭所有 hook 和状态行,无论是你的还是对话文件夹的,这样它们就无法在带有该密钥的环境中运行。托管设置中的 hook 仍会运行。使用你的 Claude 登录的对话则保留它们。

0.9.17 新增 从 Claude Code 会话内部(例如智能体的 shell)启动的中继,不再把该会话的变量(其中包括它的会话 id、消息套接字和令牌)交给它的 worker。参见从 Claude Code 内部启动的中继。

详情:机密存放在哪里、哪些变量会到达智能体的 worker。

中继之间 #

配对可能会交出令牌:如果另一个中继需要用不同的令牌来回调你的中继,介绍过程会携带你的令牌,而移除配对并不会撤销它。Agents may(智能体可以)级别和 Accept prompts from other relays' agents(接受其他中继上智能体的提示词)限制智能体通过该工具能做什么,而不是令牌持有者直接能做什么。级别分为 Read only(只读)、Read and prompt(读取并发送提示词)和 Full(完全访问),新配对从 Full 开始。已配对的中继会在对话中被锁定,直到你提及它。跨越了两个中继的提示词不会再传递给第三个,而且如果连续 30 条提示词之间都没有你发出的消息,下一条会通过卡片先征求你的确认。

详情:远程中继与配对。

同一中继上的智能体之间 #

智能体会话默认关闭。当你开启它们后,智能体在对话中启动其第一个会话之前必须询问你,它最多可有 4 个会话同时工作,而且智能体启动的会话不能自己再启动会话。在 ask 和 plan 模式下,每个写操作都会先询问。

用审批卡片上的按钮来回答。在 OAR 自己的审批卡片上,只有 Allow 这个词表示批准,不区分大小写。你输入的任何其他文字都视为拒绝,而且智能体不会从中得到拒绝的理由。

详情:智能体会话和审批卡片。

网络 #

  • 谁能连接。 localhostOnly 默认为 true,并把中继绑定到 127.0.0.1。其他任何值都会绑定所有网络接口,而且中继不检查请求来自哪里。局域网访问是明文 http,因此令牌会以未加密方式穿过你的网络(谁能连接)。
  • 隧道。 在你的网络之外,通过隧道或代理使用 HTTPS:SSH 隧道、Cloudflare Tunnel、反向代理。
  • 登录。 0.9.11 新增 同一地址在一分钟内提交十个错误令牌,就会在该分钟剩余时间内被锁定(429),这次拒绝也会被记录。来自中继自己机器、未经任何转发的请求绝不会被锁定。锁定会减缓猜测;一个足够长且随机的令牌仍然是保护。cookie 是 HttpOnly 且有效 30 天(登录保护)。
  • 地址中的令牌。 ?token= 只作用于页面地址;页面用请求头登录并移除它。但最初那个地址仍可能留在浏览器历史记录以及代理或隧道的日志中(出示令牌的方式)。
  • 实时连接。 0.9.11 新增 它只接受来自中继自身来源(origin)的浏览器,因此另一个站点上的页面无法借用你的登录 cookie 进入它。在重写 Host 请求头的代理后面,把公开来源列在 allowedOrigins 中。
  • 转发请求头。 0.9.11 新增 X-Forwarded-For、X-Forwarded-Host、X-Forwarded-Proto 和 X-Real-IP 只对中继通过 trustProxy 信任的代理生效,默认是环回地址上的一个。客户端地址(锁定、速率限制、分享访问日志)以及新分享链接的主机和协议都通过它读取,因此直接连接的客户端无法选择它们。
  • 重启与清空队列。 重启、取消重启和 Empty queue(清空队列)只需要令牌,可从任何设备发起。如果不允许远程用户使用它们,请在代理处拒绝它们(只有中继自己的机器才能使用的端点)。
  • 会话 worker 的路径保护。 你的智能体的 worker 使用的路径,以及图片操作的执行,只回应环回对等方,且其请求不带任何隧道标记(cf-ray,或 tunnelMarkerHeaders 中的某个)也没有 X-Forwarded-For、Forwarded 或 X-Real-IP。不加任何这些请求头的转发器(例如 SSH 反向隧道)看起来像本地的;那么只有令牌保护该路径(路径保护)。
  • Cloudflare 隧道令牌。 它在命令行上传递给 cloudflared,因此机器上的其他用户可以在进程列表中看到它(Cloudflare Tunnel)。
  • SSH 隧道清理。 autoReclaimPort(默认开启)会结束你 SSH 登录中占用远程端口的进程;reclaimStaleSshSessions 还会结束你在那里的空闲 SSH 会话(远程端口被占用)。

什么会离开你的机器 #

OAR 没有遥测。中继不会把用量数据发送给 OAR 或任何其他人。它只出于以下原因联系这些主机:

  • oar.sh,只有在你选择加入时。 Settings → General(设置 → 常规)中的 Check for updates automatically(自动检查更新)默认关闭。当你开启它后,中继会立即、在每次启动时以及此后大约每 12 小时询问一次 https://oar.sh/latest.json。该请求是一个普通的 GET,带 Accept: application/json,并且一旦有了答案,还会带 If-None-Match。它不携带任何版本、令牌、账户或机器信息。Check for updates(检查更新)按钮和不带 --to 的 oar update 读取同一个文件。中继环境中的 OAR_NO_UPDATE_CHECK=1 会停止这一切。参见更新检查。
  • npm,当你更新时。 npm install -g 会与 npm 注册表通信。
  • 每个提供商,每一轮。 你的消息以及智能体为任务读取的任何内容都会发送给对话背后的提供商:GitHub Copilot、OpenAI(或你设置的基础 URL)、Claude、Claude API、Cursor、Grok 或 DeepSeek(或你设置的基础 URL)。适用的是它们的条款,而不是 OAR 的。
  • DeepSeek。 0.9.17 新增 中继会把 DeepSeek 密钥发送到 https://api.deepseek.com,或发送到 Settings → Providers → DeepSeek(设置 → 提供商 → DeepSeek)中 Advanced(高级)下设置的基础 URL(https,或仅在同一台机器上的 http),而不会发送到其他主机:在保存密钥或基础 URL、或刷新 🤗 Select Models(选择模型)中的列表时列出模型,以及读取余额(见下)。DeepSeek 对话的 Claude Code 会把它的轮次发送到该地址下的 /anthropic,带有与任何 Claude Code 对话相同的会话上下文。OAR 会关闭 Claude Code 自身发往 Anthropic 的流量(更新、遥测)。参见 DeepSeek。
  • Claude API。 0.9.18 新增 中继会把 Claude API 密钥发送到 https://api.anthropic.com,而不会发送到其他主机:在保存它、开启 Claude API 或刷新列表时列出该密钥的模型。Claude API 对话的 Claude Code 会把它的轮次连同密钥发送到那里。参见 Claude API。
  • Claude Cloud。 智能体在 Anthropic、在你仓库的克隆上运行。中继会把 Claude 登录令牌发送到 https://api.anthropic.com,而不会发送到其他主机。参见 Claude Cloud。
  • 套餐用量,在你打开 Check Usage(查看用量)时。 中继用它在机器上找到的登录读取你的账户:GitHub(api.github.com,用 GH_TOKEN、GITHUB_TOKEN 或 gh 的登录)、Grok(cli-chat-proxy.grok.com,用 Grok CLI 的登录)、Anthropic(在 Claude Cloud 开启时)、0.9.17 新增 DeepSeek(在 DeepSeek 开启时,用已保存的密钥在 DeepSeek 基础 URL 读取余额),以及——只有在你输入了控制台会话令牌时——cursor.com。参见 Check Usage。
  • GitHub Actions。 为了休眠检查,中继会针对你各个工作目录所属的仓库运行 gh run list(让主机休眠)。
  • 已配对的中继。 智能体通过 relay_tool 发送的内容会连同其令牌发送到那个中继的地址(远程中继)。
  • 提供商安装程序,当你确认时。 针对 Claude 或 Grok 的 Install(安装)会以中继用户身份运行提供商自己的安装脚本(claude.ai、x.ai)(Claude、Grok)。
  • 推送通知。 它们经过你浏览器厂商的推送服务,而且除非你另有选择,文本是通用的(通知显示什么)。

是你的浏览器,而不是中继,在每次打开应用时从 cdn.jsdelivr.net(Markdown、数学、终端)和 cdnjs.cloudflare.com(高亮)加载 Markdown、数学和高亮库。当 cdn.jsdelivr.net 失败时,tmux 会话的终端视图会从 unpkg.com 加载其终端库。这些主机会看到每个打开应用的浏览器的请求。参见图片、媒体与公式。

日志 #

中继会把它的控制台复制到状态文件夹中的 logs/relay-console.log,每行带一个时间戳。它在 5 MB 时轮换,并保留三个较旧的文件。在写入一行之前,中继会把你的访问令牌以及 ?token= 或 &token= 之后的任何值替换为 [token]。OAR_NO_CONSOLE_LOG=1 会关闭该文件。单个错误令牌不会被记录;被锁定的地址会被记录,带一行以 [auth] 开头的内容。预览以短哈希命名,绝不以其令牌命名。分享读取会连同查看者的地址一起记录,当 Store viewer IP addresses(保存查看者的 IP 地址)关闭时则为 not stored。

worker 日志(worker-<session>.log)保存每个会话 worker 的输出,由 worker 自己写入,不经过上述替换。已删除对话的文件会保留。中继前面的反向代理或隧道保留自己的日志,其中可能含有 ?token= 地址,而托管的 Cloudflare 隧道会把它的令牌显示为 <redacted>。请把所有日志都视为隐私,并且在把它们发布到任何地方之前先阅读一遍。

详情:日志。

在暴露中继之前 #

  1. 保持令牌随机,并远离你分享的地址。如果它泄露了,运行 oar setup --new-token,它会让每台设备退出登录并锁定已配对的中继。
  2. 通过 HTTPS 访问中继:隧道或反向代理。当代理或隧道在同一台机器上运行时,保持 localhostOnly 开启。
  3. 在另一台机器上的代理后面,把 trustProxy 设置为它,并且如果它重写 Host,设置 allowedOrigins(另一台机器上的代理)。完全不加任何请求头的转发器需要在 tunnelMarkerHeaders 中设置一个标记请求头。如果不允许远程用户重启中继,让代理拒绝那些端点。
  4. 以一个你愿意把其权限、文件和登录都交给智能体的用户身份运行中继。如果对话只应在某些文件夹中启动,设置 workspaceRootAllowList,并记住它不会限制 shell。
  5. 只有在用 Preview as shared(预览分享效果)阅读过对话之后再分享它,并隐藏不该出现的内容。路径过滤对自由文本只能尽力而为。在 Settings → Sharing 中停止你不再需要的链接。
  6. 只发布你愿意让任何拥有链接的人看到的内容作为预览,并在完成后关闭它。它在中继重启后仍然存在。
  7. 除非你需要,否则保持智能体会话关闭。对于已配对的中继,有意识地选择 Agents may 级别,并在不需要的地方关闭 Accept prompts from other relays' agents。
  8. 点击审批卡片上的按钮。
  9. 如果你完全不希望与 oar.sh 联系,设置 OAR_NO_UPDATE_CHECK=1。