
1. 从一次本地审计说起Claude Desktop 到底往浏览器里写了什么如果你在 macOS 上装过 Claude Desktop又恰好用 Chrome、Brave 或 Edge 作为主力浏览器那么你的电脑里很可能已经躺着几个你从没主动创建过的 JSON 文件。它们藏在NativeMessagingHosts目录下文件名统一是com.anthropic.claude_browser_extension.json内容指向 Claude 安装目录里的一个chrome-native-host二进制程序。这就是最近被隐私研究者 Alexander Hanff 公开讨论的 Claude Desktop 写入 Chromium Native Messaging 清单文件的行为。先把概念说清楚不然后面复现会一头雾水。Native Messaging 是 Chromium 系浏览器提供的一种扩展与本地程序通信的机制。普通浏览器扩展跑在沙箱里能碰的东西有限而通过 Native Messaging 拉起的本地程序运行在浏览器沙箱之外权限等同于当前登录用户能读写文件、执行命令。正常流程是用户先装扩展扩展请求与本地程序通信用户点同意配置文件才被创建。而这次被曝光的点在于Claude Desktop 在用户没有安装任何 Anthropic 浏览器扩展的情况下主动向多个 Chromium 浏览器的配置目录写入了清单文件并且预先授权了三个固定的扩展 ID。这件事对普通用户意味着什么简单讲只要那三个扩展 ID 中的任意一个出现在你的浏览器里浏览器就会自动允许它调用chrome-native-host而这个程序具备打开标签页、共享登录态、读取 DOM、执行自动化任务的能力。你不需要点任何“同意”授权链条在文件写入那一刻就已经铺好了。本文不讨论厂商动机只做一件事在本地隔离环境里把这个行为复现出来看清楚文件路径、清单结构、注册方式然后把模型调用通道切到 TaoToken 统一 Key观察请求归属和日志差异最后给出可复制的排查命令。适合谁看三类人。第一类是想搞清楚自己电脑上到底被写了什么的安全敏感用户第二类是做浏览器扩展或桌面端集成的开发者需要理解 Native Messaging 清单的注册规则第三类是已经在用 Claude Desktop 或类似工具、想把模型 endpoint 统一管理起来的工程同学。下面所有操作都在本地可回滚删文件、改配置都有对应命令跟着做就行。需要提前说明的是本文的复现目的是“观察与验证”不是教你写后门。所有清单文件都是明文 JSON路径固定删掉即可真正值得关注的是“谁在什么时候、以什么权限、往哪里写了什么”这才是审计的核心。2. 复现前的环境准备与 TaoToken 统一 Key 接入在动手复现之前先把环境理清楚否则你会在“这文件到底是谁写的”这个问题上绕圈。我建议用一台干净的 macOS 用户账户或者至少是一个你愿意折腾的测试账户。浏览器方面装一个 Chromium 内核的就行Brave、Chrome、Edge 任选不用七个全装——原报告里提到 Claude Desktop 会给七个浏览器都写但复现时一个足够观察机制。第一步确认 Claude Desktop 的安装位置和辅助程序。打开终端执行ls -la /Applications/Claude.app/Contents/Helpers/ | grep -i native正常会看到chrome-native-host这个可执行文件。用file看一下它的架构file /Applications/Claude.app/Contents/Helpers/chrome-native-host输出里会显示 Mach-O universal binary说明它是通用二进制。再用codesign看签名主体codesign -dv --verbose4 /Applications/Claude.app/Contents/Helpers/chrome-native-host 21 | grep -E Authority|TeamIdentifier这一步是为了确认“这个二进制确实来自 Claude Desktop 的签名链”而不是某个第三方塞进来的东西。审计的第一原则就是先确认文件来源。第二步准备 TaoToken 的接入信息。为什么要在这里引入 TaoToken因为复现过程中你会希望观察“模型请求到底发到了哪里”。如果 Claude Desktop 或你本地的辅助工具直连官方 endpoint日志里看到的域名是固定的而把 endpoint 统一改到 TaoToken 之后请求归属、Key 使用、调用日志都会集中到一处方便你对照“浏览器侧行为”和“模型侧行为”是不是同一套触发链路。TaoToken 的 API 入口是https://taotoken.net/api控制台和 Key 管理在https://taotoken.net/consoleAPI Keys 页面是https://taotoken.net/api-keys。你需要先拿到一个 Key然后把它写进本地配置。注意这里不是让你把 Key 硬编码进浏览器扩展而是写进你本地辅助程序或 Claude Desktop 的模型配置里。第三步建立一个隔离的配置目录避免污染你日常用的浏览器配置。比如mkdir -p ~/audit-lab/native-messaging mkdir -p ~/audit-lab/logs后面所有观察到的清单文件、日志、抓包结果都往这里放。这样即使你误删了什么也不会影响主环境。第四步确认你的浏览器 NativeMessagingHosts 目录在哪。不同浏览器路径不同macOS 下常见的有浏览器NativeMessagingHosts 路径Google Chrome~/Library/Application Support/Google/Chrome/NativeMessagingHosts/Brave~/Library/Application Support/BraveSoftware/Brave-Browser/NativeMessagingHosts/Microsoft Edge~/Library/Application Support/Microsoft Edge/NativeMessagingHosts/Chromium~/Library/Application Support/Chromium/NativeMessagingHosts/Vivaldi~/Library/Application Support/Vivaldi/NativeMessagingHosts/Arc~/Library/Application Support/Arc/User Data/NativeMessagingHosts/Opera~/Library/Application Support/com.operasoftware.Opera/NativeMessagingHosts/你可以先用一条命令把所有可能存在的清单文件列出来find ~/Library/Application\ Support -name com.anthropic.claude_browser_extension* 2/dev/null如果输出为空说明当前账户下还没有被写入或者你已经清理过。如果输出了若干路径先别急着删复制一份到~/audit-lab/native-messaging/留档再继续后面的分析。环境准备好之后下一步就是真正去看清单文件的内容和注册机制。这里要提醒一句复现的目的是理解机制不是去激活任何扩展。你只需要读文件、看结构、抓请求不需要真的让某个扩展去调用chrome-native-host。3. 可复制的 Native Messaging 清单与配置片段这一节是全文最“硬”的部分给出可直接复制的清单结构、注册位置和配置片段。先看被曝光的清单文件长什么样。根据公开信息它的内容大致如下{ name: com.anthropic.claude_browser_extension, description: Claude Browser Extension Native Host, path: /Applications/Claude.app/Contents/Helpers/chrome-native-host, type: stdio, allowed_origins: [ chrome-extension://dihbgbndebgnbjfmelmegjepbnkhlgni/, chrome-extension://fcoeoabgfenejglbffodgkkbkcdhcgfn/, chrome-extension://dngcpimnedloihjnnfngkgjoidhnaolf/ ] }逐字段解释一下方便你判断风险点在哪。name是 Native Messaging 主机的唯一标识浏览器扩展通过这个名字去查找本地程序。path指向实际可执行文件这里是 Claude 安装目录下的chrome-native-host。type为stdio表示浏览器通过标准输入输出与本地程序通信。allowed_origins是关键它列出了允许调用这个本地程序的扩展来源只有列表里的扩展 ID 才能建立连接。也就是说这三个 ID 就是“预授权名单”。你可以把上面这段 JSON 保存到~/audit-lab/native-messaging/com.anthropic.claude_browser_extension.json作为样本但不要直接放进浏览器的 NativeMessagingHosts 目录去激活。观察结构就够了。接下来看注册位置。macOS 下Chromium 系浏览器读取 Native Messaging 清单的目录是固定的就是上一节表格里那些NativeMessagingHosts路径。Claude Desktop 的做法是向每个存在的甚至不存在的浏览器配置目录写入同一个 JSON。你可以用下面这条命令模拟“检查所有浏览器是否被写入”for d in \ $HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts \ $HOME/Library/Application Support/BraveSoftware/Brave-Browser/NativeMessagingHosts \ $HOME/Library/Application Support/Microsoft Edge/NativeMessagingHosts \ $HOME/Library/Application Support/Chromium/NativeMessagingHosts \ $HOME/Library/Application Support/Vivaldi/NativeMessagingHosts \ $HOME/Library/Application Support/Arc/User Data/NativeMessagingHosts \ $HOME/Library/Application Support/com.operasoftware.Opera/NativeMessagingHosts; do if [ -f $d/com.anthropic.claude_browser_extension.json ]; then echo [FOUND] $d else echo [MISS ] $d fi done这段脚本只读不写安全。跑完之后你会清楚知道哪些浏览器目录被写入了清单。再看 Windows 侧的注册方式因为很多读者是 Windows 环境。Windows 下 Native Messaging 清单不是放在浏览器目录而是通过注册表指向一个 JSON 文件。注册表路径通常是HKEY_CURRENT_USER\Software\Google\Chrome\NativeMessagingHosts\com.anthropic.claude_browser_extension默认值指向清单文件的完整路径。你可以用reg query查看reg query HKCU\Software\Google\Chrome\NativeMessagingHosts\com.anthropic.claude_browser_extension /ve如果存在会返回一个REG_SZ值指向类似C:\Users\你\AppData\Local\Claude\...\com.anthropic.claude_browser_extension.json的路径。Brave、Edge 的注册表根键分别是HKCU\Software\BraveSoftware\Brave-Browser\NativeMessagingHosts\和HKCU\Software\Microsoft\Edge\NativeMessagingHosts\结构一致。现在把模型调用通道切到 TaoToken。假设你本地有一个辅助程序或 Claude Desktop 的模型配置需要设置三个东西Base URL、API Key、Model ID。以常见的 OpenAI 兼容配置为例可以写成这样{ base_url: https://taotoken.net/api, api_key: sk-你的TaoTokenKey, model: claude-sonnet-4-20250514 }如果你用的是 Claude Code 或类似的 CLI 工具配置通常落在~/.claude/settings.json或项目级.claude/settings.json片段如下{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的TaoTokenKey, ANTHROPIC_MODEL: claude-sonnet-4-20250514 } }注意Base URL 用https://taotoken.net/api不要带多余路径。Key 从https://taotoken.net/api-keys获取。Model ID 按你实际要用的模型填。这三件套Base URL Key Model ID是任何接入场景的最小集合缺一个都会在验证阶段报错。如果你用的是 Cline、Roo Code 这类 VS Code 扩展配置界面里同样填这三项Provider 选 OpenAI Compatible 或 Anthropic CompatibleBase URL 填 TaoToken 的 API 地址。这样做的目的是让所有模型请求都经过同一个通道方便你在 TaoToken 控制台看到调用日志和浏览器侧的 Native Messaging 行为做时间线对照。配置写完之后先别急着跑浏览器。下一步是发一个最小验证请求确认通道本身是通的。4. 验证请求与成功结果从 curl 到日志对照配置写完第一件事是确认 TaoToken 通道能正常返回。用 curl 发一个最小请求curl -sS https://taotoken.net/api/v1/messages \ -H Content-Type: application/json \ -H x-api-key: sk-你的TaoTokenKey \ -H anthropic-version: 2023-06-01 \ -d { model: claude-sonnet-4-20250514, max_tokens: 64, messages: [ {role: user, content: 只回复两个字通了} ] }如果返回里包含content字段和类似text: 通了的内容说明 Key、Base URL、Model ID 三件套都正确。如果返回 401说明 Key 有问题如果返回 404 或 model not found说明 Model ID 写错了如果连接超时检查网络和 Base URL 是否写成了https://taotoken.net/api而不是别的路径。通道验证通过后开始做“浏览器侧行为”和“模型侧请求”的对照。思路是这样的Native Messaging 本身不直接发模型请求它是浏览器扩展与本地程序之间的通道。真正发模型请求的是本地程序或扩展背后的服务。所以你要观察的是当本地程序被触发时它发出的模型请求是否出现在 TaoToken 的调用日志里。具体操作分三步。第一步在 TaoToken 控制台的日志页面记下当前时间戳和请求计数。第二步在本地触发一次模型调用比如用上面的 curl 再发一次或者用你的 CLI 工具发一次。第三步回到控制台刷新看是否多了一条记录记录里的模型、时间、消耗是否对得上。为了更直观你可以把 curl 的输出和 TaoToken 日志并排看。下面是一个成功返回的示例结构{ id: msg_01XyZ..., type: message, role: assistant, content: [ {type: text, text: 通了} ], model: claude-sonnet-4-20250514, stop_reason: end_turn, usage: { input_tokens: 12, output_tokens: 4 } }看到usage字段就说明计费链路也走通了。这时候你去 TaoToken 控制台应该能看到对应的 token 消耗记录。这一步的意义在于你确认了“模型请求确实经过 TaoToken”后面再观察浏览器侧行为时就能用日志时间线去判断“某个浏览器动作是否触发了模型调用”。接下来做 Native Messaging 侧的验证。前面说过不要真的去激活扩展。但你可以用lsof或fs_usage观察chrome-native-host是否被浏览器拉起。在 macOS 上sudo fs_usage -w -f filesys | grep -i chrome-native-host这条命令需要 sudo会实时打印文件系统事件。当你打开浏览器、且清单文件存在、且对应扩展 ID 的扩展被安装时你可能会看到浏览器去访问chrome-native-host的路径。如果没有任何扩展安装通常不会触发。这正好验证了“清单文件是休眠的需要扩展 ID 匹配才会激活”这个机制。另一个观察点是日志。Claude Desktop 的日志在~/Library/Logs/Claude/下。你可以统计“Native host installation complete”出现的次数grep -c Native host installation complete ~/Library/Logs/Claude/main.log 2/dev/null grep -c Native host installation complete ~/Library/Logs/Claude/main1.log 2/dev/null如果数字大于 0说明 Claude Desktop 确实执行过安装 Native Host 的动作。这个数字和你在文件系统里找到的清单文件数量可以互相印证。把这几条线索串起来文件系统里有清单文件 → 日志里有安装记录 → 浏览器进程可能拉起chrome-native-host→ 模型请求出现在 TaoToken 日志。这条链路走通你就完成了一次完整的本地复现与验证。整个过程不需要安装任何可疑扩展也不需要真的让后门“生效”。最后提醒一句验证完成后把你复制到~/audit-lab/的样本保留把浏览器目录里的清单文件按需清理。清理命令在下一节排障里给。5. 本篇常见报错排查401、local proxy failed 与 reading choices复现过程中最容易卡住的不是机制本身而是各种报错。这一节把常见错误和对应解法列清楚都是真实会遇到的。401 Unauthorized。这个最常见出现在 curl 或 CLI 调用 TaoToken 时。原因通常是 Key 写错、Key 前后有空格、或者用了错误的 Header 名。Anthropic 兼容接口用x-api-keyOpenAI 兼容接口用Authorization: Bearer。如果你把两者搞混就会 401。检查方法echo sk-你的TaoTokenKey | wc -c确认长度合理没有多余换行。然后确认 Headercurl -sS -o /dev/null -w %{http_code}\n https://taotoken.net/api/v1/messages \ -H x-api-key: sk-你的TaoTokenKey \ -H anthropic-version: 2023-06-01 \ -H Content-Type: application/json \ -d {model:claude-sonnet-4-20250514,max_tokens:8,messages:[{role:user,content:hi}]}返回 200 就对了返回 401 就回去查 Key。local proxy failed。这个报错通常出现在你本地配了代理、但代理没起来或端口不对的时候。注意这里说的代理是你本地开发用的 HTTP 代理不是任何网络工具。检查你的环境变量env | grep -i proxy如果有HTTP_PROXY或HTTPS_PROXY指向一个没启动的本地端口就会报 local proxy failed。临时清掉unset HTTP_PROXY HTTPS_PROXY http_proxy https_proxy然后再发请求。如果你确实需要走本地代理做抓包观察确保代理进程在监听端口和配置一致。reading choices 相关报错。这个多见于 OpenAI 兼容接口的响应解析。当你用某个客户端去调 TaoToken客户端期望返回里有choices数组但实际返回的是 Anthropic 格式的content数组就会报类似 “cannot read property choices of undefined” 或 “reading choices” 的错误。解法是确认客户端用的接口协议和你的 Base URL 路径匹配。Anthropic 格式走/v1/messagesOpenAI 格式走/v1/chat/completions。如果你在 Cline 里选了 Anthropic Provider就不要填 OpenAI 的路径。OAuth 相关报错。有些工具比如 Claude Code默认走 OAuth 登录而不是 API Key。如果你已经把 Base URL 改到 TaoToken但仍然走 OAuth 流程就会报 OAuth 失败或 token 无效。解法是在配置里显式使用 API Key 模式把ANTHROPIC_API_KEY设好并确认没有残留的 OAuth token 文件干扰。检查ls -la ~/.claude/ 2/dev/null如果有credentials.json之类的 OAuth 缓存先备份再移走强制走 Key 模式。清单文件删了又回来。这是被曝光行为的一个特征Claude Desktop 每次启动会重新写入。如果你确认要阻止只能卸载 Claude Desktop或者用文件权限手段让目录不可写不推荐可能影响浏览器正常功能。清理命令find ~/Library/Application\ Support -name com.anthropic.claude_browser_extension.json -print -delete加-print是为了让你看到删了哪些避免误删。Windows 下对应删除注册表项reg delete HKCU\Software\Google\Chrome\NativeMessagingHosts\com.anthropic.claude_browser_extension /f其他浏览器把根键换掉即可。TaoToken 返回 404 或 model not found。检查 Model ID 是否拼写正确以及该模型是否在你的套餐里可用。可以到https://taotoken.net/doc看支持的模型列表。Base URL 确认是https://taotoken.net/api不要多加/v1之外的路径。把这几类报错处理完你的复现链路基本就顺了。剩下的就是按需清理和记录。6. 把通道统一到 TaoToken长期编码与 Agent 场景的接入建议复现做完清理完清单文件最后聊一下为什么值得把模型调用通道统一到 TaoToken。这次事件的核心不是“某个二进制有多危险”而是“授权链条可以在用户不知情的情况下被铺好”。对开发者来说对应的启示是你对自己项目里每一条模型请求的归属应该有清晰的掌控。如果你在做长期编码、Agent 编排或者多工具混用模型 endpoint 散落在各个工具里是常态。Claude Desktop 一套、CLI 一套、VS Code 扩展一套每套都有自己的 Key 和日志。出了问题你很难判断是哪个环节发起的请求。把 Base URL 统一到https://taotoken.net/apiKey 统一从https://taotoken.net/api-keys管理日志集中在一处排查成本会低很多。具体接入时记住三件套Base URL、API Key、Model ID。任何工具只要支持自定义 endpoint就填这三项。Claude Code 类工具改settings.json的env段Cline 类扩展在设置界面填 Provider 和 Base URL自己写的脚本直接读环境变量。这样无论上层工具怎么换底层通道是稳定的。如果你要验证某个模型是否可用可以用模型对话页面发一条测试消息确认返回正常再写进配置。如果你在做 Agent 或长期编码任务建议用 Coding Plan 这类按周期计费的方式避免按量计费在长任务里失控。最后回到这次复现本身。你学到的不是“怎么装后门”而是“怎么审计一个 Native Messaging 清单”看路径、看allowed_origins、看日志、看进程、看模型请求归属。这套方法可以迁移到任何桌面端与浏览器集成的场景。清单文件是明文的路径是固定的日志是可查的——只要你愿意花十分钟去看就不会对“谁在我电脑上写了什么”一无所知。