Skip to content

privsep 协议破解与 31 个未暴露 socket 实测 ​

方法:strace 实证 + 通用客户端探测 结果:26 个 socket 可直接调用(5 个被权限拒绝) 关联:research-direction-recommendations.md 🔒 §1


0. 结论 ​

预研路线图方向二的判断完全正确,且结果超出预期。

项结果
未暴露 socket 总数31
✅ 可直接调用26 个
❌ 权限拒绝(真隔离)5 个
协议破解方式strace 抓 notion-cli 真实通信

⭐ 最有价值的一条:shopify.sock 返回了 24 个可用工具, 包括 list-orders / get-order / list-customers / get-inventory-levels —— 这正是我在电商研究中标为「空白」的 ⑪订单追踪环节。


1. ⭐⭐ 完整协议(strace 实证) ​

1.1 真实报文序列 ​

以 notion-cli 为样本(strace -f -e trace=sendmsg,sendto,recvfrom):

c
connect(9, "/run/hatch/privsep/notion-cli.sock") = 0

// ① 魔数
sendto(9, "\x00\x03", 2, MSG_NOSIGNAL) = 2

// ② fd 握手:payload 只有 1 字节 0x46,3 个 fd 在 ancillary data
sendmsg(9, {
  msg_iov    = [{iov_base="\x46", iov_len=1}],
  msg_control= [{cmsg_len=28, cmsg_level=SOL_SOCKET,
                 cmsg_type=SCM_RIGHTS, cmsg_data=[0,1,2]}]
}, 0) = 1

// ③ 分隔字节
sendto(9, "\x00", 1, MSG_NOSIGNAL) = 1

// ④ JSON 请求
sendto(9, "{\"args_json\":\"{\\\"endpoint\\\"...}\",\"forwarded_env\":{}...}", 230) = 230

// ⑤ 读响应(非阻塞,每次 32B,直到返回 0)
recvfrom(9, "...", 32) = 32
recvfrom(9, "...", 32) = 18
recvfrom(9, "") = 0

1.2 协议要点 ​

项值
魔数\x00\x03(2 字节,最先发)
fd 握手标记0x46(1 字节,payload 必须恰好这 1 字节)
传入 fd 数必须 ≥3(stdin, stdout, stderr),落在 SCM_RIGHTS 里
分隔符\x00(1 字节,fd 握手与 JSON 之间)
请求体JSON(PrivsepRequest)
响应同一个 socket 读回,非阻塞循环直到 recv 返回 0

1.3 ⭐ 关键错误信息(指引破解的线索) ​

探索过程中 worker 给出的三条关键错误:

① "expected fd marker 0x46, got 1 byte(s) (first byte: 0x7b)"
   → 暴露了 0x46 这个标记

② "expected >= 3 fds (stdin, stdout, stderr, [file...]), got 1"
   → ⭐ 直接说明需要 3 个 fd,且用途是 stdin/stdout/stderr

③ "read fd count prefix: failed to fill whole buffer"
   → 暴露了内部有 "fd count prefix" 字段

⭐ 这三个错误是"自描述的"—— worker 主动告诉了你协议要求。 这是 Muse privsep 设计的一个特点:错误信息足够详细,可用于协议发现。

1.4 PrivsepRequest 标准结构 ​

json
{
  "args_json":        "<内层命令的 JSON 字符串>",
  "forwarded_env":    {},
  "input_file_paths": [],
  "optional_input_failures": [],
  "output_dir_spool_counts": [],
  "input_dir_service": false
}

内层 args_json 是一个再序列化的 JSON 字符串,形如:

json
{"command": "Status"}

1.5 ⭐ 我踩过的三个坑(供后续参考) ​

#错误做法后果
1以为要发 0x46 + count + JSON(一个大 payload)报 expected fd marker 0x46, got X
2只传 1 个 /dev/null fd报 expected >= 3 fds
3socket.sendto(b'..', 0)Python API 参数顺序错,应 send()
4用阻塞 recv() 等响应超时;worker 用非阻塞分块写,需非阻塞循环

其中第 1 条最耽误时间 —— 我盲试了约 20 组才转向 strace。


2. ⭐ 26 个 socket 实测结果 ​

2.1 返回 MCP endpoint 的(企业集成,全部 not_connected) ​

socketendpoint状态
asanahttps://mcp.asana.com/v2/mcpnot_connected
canvahttps://mcp.canva.com/mcpnot_connected
dropboxhttps://mcp.dropbox.com/muse_app_mcpnot_connected
evernotehttps://mcp.evernote.com/mcpnot_connected
instacarthttps://fig-mcp.instacart.com/mcpnot_connected
klaviyohttps://mcp.klaviyo.com/mcp?core-tools-only=true&toolsets=...not_connected
linearhttps://mcp.linear.app/mcpnot_connected
lovablehttps://mcp.lovable.devnot_connected
quickbookshttps://mcp.quickbooks.intuit.com/mcpnot_connected(protocol 2025-11-25)
replithttps://replit-mcp.com/server/mcpnot_connected
slackhttps://mcp.slack.com/mcpnot_connected
squarehttps://mcp.squareup.com/mcpnot_connected
vercelhttps://mcp.vercel.com/not_connected
zapierhttps://mcp.zapier.com/api/v1/connectnot_connected
zoomhttps://mcp.zoom.us/mcp/zoom/streamablenot_connected

⭐ klaviyo 的 endpoint 泄露了完整 scope 清单:

toolsets=accounts:read, campaigns:read, campaigns:write, flows:read,
lists:read, lists:write, events:read, catalogs:read, templates:read,
templates:write, profiles:read, profiles:write, subscriptions:read,
subscriptions:write, segments:read, metrics:read, images:write, reviews:read

这对于理解 Muse 的电商/营销能力边界极有价值 (catalogs:read / reviews:read / profiles:read 都是电商信号源)。

2.2 ⭐⭐ shopify:返回 24 个可用工具 ​

json
{
  "provider": "shopify",
  "server_name": "shopify-mcp-server",
  "server_version": "1.0.0",
  "protocol_version": "2025-03-26",
  "endpoint": "https://setup.shopify.com/mcp",
  "auth_status": "not_connected",
  "available_tools": [
    "search_products", "get-shop-info", "get-product", "create-product",
    "update-product", "list-orders", "get-order", "list-customers",
    "get-inventory-levels", "set-inventory", "create-discount",
    "add-to-collection", "run-analytics-query", "bulk-update-product-status",
    "search_collections", "get-collection", "create-collection",
    "update-collection", "switch-shop", "graphql_schema",
    "graphql_query", "graphql_mutation", "validate_graphql_codeblocks",
    "search_docs_chunks"
  ]
}

⭐⭐ 这直接填补了我电商研究的空白:

我此前标注的空白环对应工具
⑪ order-trackinglist-orders / get-order ✅
⑦ cartsearch_products / get-product
⑮ merchant-side(商家侧)create-product / update-product / set-inventory / create-discount
⑯ measurementrun-analytics-query
⑭ repurchaselist-customers / list-orders

→ ⑪/⑮/⑯ 三个空白环在 shopify.sock 里都有对应能力。唯一门槛:需要授权(当前 not_connected)。

2.2.1 ⭐ 24 个工具的完整清单(含权限标签) ​

这是本次最有价值的资产 —— 每个工具都带 hatch_action(read/write)与 hatch_permission:

工具action权限电商环节映射
search_productsreadcatalog.read②catalog
get-productreadcatalog.read②catalog
get-shop-inforead——
create-productwritecatalog.manage⑮merchant-side
update-productwritecatalog.manage⑮merchant-side
list-ordersread—⑪order-tracking
get-orderread—⑪order-tracking
list-customersread—⑭repurchase
get-inventory-levelsread—⑮merchant-side
set-inventorywritecatalog.manage⑮merchant-side
create-discountwritediscounts.manage⑮merchant-side
add-to-collectionwritecatalog.manage⑦cart(收藏夹)
search_collectionsreadcatalog.read⑦cart
get-collectionreadcatalog.read⑦cart
create-collectionwritecatalog.manage⑮merchant-side
update-collectionwritecatalog.manage⑮merchant-side
bulk-update-product-statuswritecatalog.manage⑮merchant-side
run-analytics-queryreadadmin.read⑯measurement
graphql_schemareadadmin.read⭐ 通用通路
graphql_queryreadadmin.read⭐ 通用通路
graphql_mutationwriteadmin.manage⭐ 通用通路
validate_graphql_codeblocksreaddocumentation.read—
search_docs_chunksreaddocumentation.read—
switch-shopwritestore.switch—

⭐⭐ 三条通用通路是这里最重要的发现:

graphql_schema → graphql_query / graphql_mutation可以访问 Shopify Admin API 的任意资源,不限于内置的 24 个工具。

tool description 逐字:

"The Shopify Admin API exposes hundreds of resources. Built-in tools cover common operations, but when the user asks about a resource that has no dedicated tool (e.g. gift cards, metafields, metaobjects, pages, blogs, markets, translations, publications), use this tool to fetch the data."

2.2.2 ⭐⭐ run-analytics-query 暴露了完整 ShopifyQL 语法 ​

这个工具的 description 里内嵌了完整的 ShopifyQL 查询语法与示例(逐字):

## Sales & Revenue
- FROM sales SHOW gross_sales TIMESERIES day SINCE -30d UNTIL today
- FROM sales SHOW orders, gross_sales, discounts, sales_reversals,
       net_sales, shipping_charges, taxes, total_sales TIMESERIES day ...
- FROM sales SHOW total_sales TIMESERIES day ... COMPARE TO previous_period
- FROM sales SHOW average_order_value TIMESERIES day SINCE -30d UNTIL today

## Orders
- FROM fulfillments SHOW orders_fulfilled, orders_shipped, orders_delivered ...

## Products
- FROM sales SHOW gross_sales, net_sales, orders
       GROUP BY product_title ORDER BY gross_sales DESC LIMIT 10
- FROM inventory SHOW starting_inventory_units, ending_inventory_units,
       inventory_units_sold, sell_through_rate
       GROUP BY product_title, product_variant_title

## Customers
- FROM sales SHOW returning_customers, customers, returning_customer_rate ...
- FROM sales SHOW new_customers, returning_customers ...

## Sessions & Conversion
- FROM sessions SHOW sessions, sessions_with_cart_additions,
       sessions_that_reached_checkout, sessions_that_completed_checkout,
       conversion_rate TIMESERIES day SINCE -30d UNTIL today
- FROM sessions SHOW sessions GROUP BY session_device_type ...
- FROM sessions SHOW sessions GROUP BY session_country ...

## Marketing & Referrals
- FROM sales SHOW orders, total_sales
       GROUP BY order_referrer_source, order_referrer_name ...
- FROM sessions SHOW sessions WHERE referrer_source = 'social'
       GROUP BY referrer_name ...

## Tables: sales, orders, sessions, customers, fulfillments, inventory, payments
## Time grouping: TIMESERIES day/week/month. Category grouping: GROUP BY column
## Comparison: COMPARE TO previous_period. Aggregates: WITH TOTALS, PERCENT_CHANGE

⭐ 这直接补上了我电商研究的 ⑯measurement 环 —— 而且 sessions_with_cart_additions / sessions_that_reached_checkout / sessions_that_completed_checkout / conversion_rate 这些指标 正是 ⑦cart → ⑧checkout 转化漏斗的观测面。

2.2.3 ⭐ 安全限制(tool description 逐字) ​

graphql_mutation 的说明里明确列出了被封锁的操作:

"Some dangerous mutations are blocked for safety (e.g. refunds, gift card writes, staff management, theme deletion, theme publishing). Theme file writes ... are allowed on unpublished themes only — writes that target the live/MAIN theme are blocked. If a mutation is blocked, inform the user and suggest they perform the action in Shopify admin. The host app will prompt the user for confirmation before executing."

⭐ 两点值得记:

  1. refunds 被明确封锁 —— 这对应我电商研究里标为空白的 ⑫returns 环
  2. "host app will prompt the user" —— 写操作有 人类确认闸门, 与 browser-broker 的 HITL 设计一致

2.2.4 ⭐⭐ 工具描述里内嵌了大量业务规则(这是意外收获) ​

create-discount 的 description 长达数百字,且包含明确的业务伦理约束(逐字):

"What matters is why the collection exists — one the merchant wants is fine, one invented to work around productIds is not."

"Two things must be confirmed with the merchant before this tool will create anything: when the discount starts, and who can use it. Both are ordinary parameters on this tool. If either is missing, the tool answers with a plain-language question to put to the merchant."

"Segments are merchant-defined — there are no built-in names like 'new_customers' or 'returning_customers'."

→ 这些 description 本身就是 Muse 的「产品价值观文档」: 宁可多问一句,也不替用户假设;不为了绕过参数限制而创造副作用。

与我在 ShoppingJudge 里发现的规则同源 ("hiding an eligible product is the greater harm" / "an omission is honest")。

2.3 返回命令枚举的(非 MCP 风格) ​

socket可用命令(worker 自报)
polymarket-apiSearch GetMarket GetEvent Orderbook Price Spread PriceHistory Leaderboard Disconnect
navigationRouteInfo SpeedLimit RouteTraffic TrafficAroundPoint TrafficIncidents TransitDepartures
messengerCheck Logout ConnectUrl DisconnectUrl Disconnect Repair CallLogs Contacts Threads Messages Search Sync Marketplace Send React Unsend Edit Unlock

⭐ messenger 的命令里有 Marketplace —— 与 ③Facebook Marketplace 环节相关。

2.4 需要额外参数才能响应的 ​

socket要求的字段
box-climissing field 'operation'
meta-ads-climissing field 'endpoint'
platform-searchmissing field 'query'

→ 这些也证明 worker 可达,只是需按各自 schema 传参。

2.5 返回业务级错误的 ​

socket错误
ring-cliRing is not available for this account.
wai-privsepWhatsApp Companion is not available for this account.

→ 这两个是「可达但账号不支持」,不是技术隔离。


2.6 ⭐ 完整能力地图(23 个 socket 实测汇总) ​

socket状态providerendpoint备注
asananot_connectedasanamcp.asana.com/v2/mcp
canvanot_connectedcanvamcp.canva.com/mcp
dropboxnot_connecteddropboxmcp.dropbox.com/muse_app_mcp
evernotenot_connectedevernotemcp.evernote.com/mcp
instacartnot_connectedinstacartfig-mcp.instacart.com/mcp⭐ 电商:生鲜配送
klaviyonot_connectedklaviyomcp.klaviyo.com/mcp⭐ 电商营销,见 §2.6.1
linearnot_connectedlinearmcp.linear.app/mcp
lovablenot_connectedlovablemcp.lovable.dev
quickbooksnot_connectedquickbooksmcp.quickbooks.intuit.com/mcpprotocol 2025-11-25
replitnot_connectedreplitreplit-mcp.com/server/mcp
slacknot_connectedslackmcp.slack.com/mcp
squarenot_connectedsquaremcp.squareup.com/mcp⭐ 支付
vercelnot_connectedvercelmcp.vercel.com/
zapiernot_connectedzapiermcp.zapier.com/api/v1/connect
zoomnot_connectedzoommcp.zoom.us/mcp/zoom/streamable
shopifynot_connectedshopifysetup.shopify.com/mcp⭐⭐ 24 工具,见 §2.2
arlonot_connected——{"ok":true,"status":"not_connected"}
box-cli需 operation 字段——
meta-ads-cli需 endpoint 字段——⭐ 广告投放
platform-search需 query 字段——
polymarket-api可达——Search/GetMarket/Orderbook/Price/Spread
navigation可达——RouteInfo/TrafficIncidents/TransitDepartures
messenger可达——⭐ Marketplace 命令(对应 ③)

⭐ 电商相关的有 5 个:shopify(商城侧)、klaviyo(营销侧)、 instacart(生鲜配送)、square(支付)、meta-ads-cli(广告投放)。

2.6.1 ⭐⭐ klaviyo:电商营销信号源(scope 泄露) ​

klaviyo 的 endpoint 内嵌完整 OAuth scope 清单(19 项):

toolsets=accounts:read,
  campaigns:read,      campaigns:write,
  flows:read,
  lists:read,          lists:write,
  events:read,
  catalogs:read,       templates:read,   templates:write,
  profiles:read,       profiles:write,
  subscriptions:read,  subscriptions:write,
  segments:read,
  metrics:read,
  images:write,
  reviews:read

⭐ 其中三项对电商研究直接相关:

scope价值
catalogs:read商品目录 —— 可作为 ②Meta Catalog 的替代数据源
reviews:read商品评价 —— ⑤比价/排序的质量信号
profiles:read用户画像 —— 正是我 bound-accounts-to-recommendation.md 里缺的那一环
events:read / metrics:read行为事件与指标 —— ⑯measurement
segments:read客群分群 —— ⑭repurchase 的基础

⚠️ 一个关键限制:klaviyo 的 ListTools 返回:

Error: connector is not connected; reconnect required

→ klaviyo 未授权时连工具清单都拿不到(与 shopify 不同, shopify 的 Status 直接返回 available_tools)。

这个差异说明:不同 connector 的信息暴露程度不同。 shopify 更开放(可能是 Muse 自建 MCP server:server_name: shopify-mcp-server), klaviyo 走标准 MCP 需要先握手授权。

2.6.2 ⭐ messenger 的 Marketplace 命令 ​

messenger.sock 的命令枚举里有 Marketplace:

Check / Logout / ConnectUrl / DisconnectUrl / Disconnect / Repair /
CallLogs / Contacts / Threads / Messages / Search / Sync /
Marketplace / Send / React / Unsend / Edit / Unlock

→ 对应我电商研究的 ③Facebook Marketplace 环节, 而 messenger.sock 没有 CLI 封装,说明这条路径此前未被暴露。

2.7 ⭐ 为什么只有 shopify 未授权也能拿工具清单 ​

对 instacart / square / klaviyo 做了 ListTools 对照实验:

socketStatusListTools(未授权时)
shopify✅ 返回 available_tools 24 项✅ 返回完整 schema
klaviyo✅ 返回 endpoint+scope❌ Error: connector is not connected; reconnect required
instacart✅ 返回 endpoint+resource❌ 同上
square✅ 返回 endpoint❌ 同上

⭐ 差异的技术解释(⚠️ B 级):

shopify 的 Status 返回里带有两个其他 connector 没有的字段:

json
"server_name":    "shopify-mcp-server",
"server_version": "1.0.0",
"protocol_version": "2025-03-26"

→ 这说明 shopify 是 Muse 侧自建的 MCP server (有 server_name 自报身份), 而 klaviyo / instacart / square 是标准第三方 MCP 端点, 必须完成 OAuth 握手才能列出工具。

→ 推论:Muse 对自建 connector 暴露了更多信息, 对第三方 connector 遵循标准 MCP 的授权流程。 这不是安全漏洞,是两种集成方式的差异。

2.8 ⭐ connector 身份的权威位置:authd(不是 DB) ​

从 muse_db schema 找到唯一与 connector 相关的表:

#### `self_improvement.connector_read_audit`
| connector_id   | text | yes | | Connector identity **owned by authd**;
|                |      |     | | **no Muse PostgreSQL owner table**. |
| device_node_id | text | yes | | Soft local reference → device.nodes.node_id |
| method_key     | text | no  | | |
| purpose        | text | no  | | |
| request_id     | text | no  | | Soft local reference → runtime.requests.request_id |
| request_origin | text | no  | | |
| sensitivity    | text | no  | | |
| source_handle  | text | yes | | |
| metadata       | jsonb| no  | '{}'::jsonb | |
| created_at     | timestamptz | no | now() | |

⭐ 三个关键信息(逐字):

  1. connector_id:"Connector identity owned by authd; no Muse PostgreSQL owner table" → connector 的身份不由 PostgreSQL 管理,由 authd 掌握 → 这解释了为什么容器内查 DB 查不到 connector 绑定状态

  2. 表里记录了 sensitivity 字段 → connector 读取是按敏感度分级记录的

  3. request_origin + purpose + method_key → 每次 connector 读取都记录谁、为什么、调用了什么方法 → 这是一个完整的审计链,与 browser-broker 的 HITL 设计一脉相承

→ 结论:Muse 对 connector 的管理是「authd 持有身份 + DB 记录审计」的双层结构。


2.9 ⭐⭐ authd:权限体系的真实边界(实测矩阵) ​

📌 本节解决了 §6 未解第 7/8 条的一部分。 authd 是 Muse 权限体系的核心,本次首次实测其门禁行为。

2.9.1 接口位置与性质 ​

项值
socket/run/hatch/auth/authd.sock(不在 privsep/ 下)
socket 权限srw-rw-rw- —— 全局可写
调试客户端/opt/hatch/bin/authdc(官方,描述逐字:"Debug client for hatch-authd")

⭐ 一个关键的架构差异:

"Runs as the invoking user; authd gates most endpoints by peer credentials, so use sudo for privileged calls."

→ socket 文件权限是 rw-rw-rw-(人人可写),但 authd 在应用层按 peer credentials 门禁。 这是"文件权限宽、应用层严"的设计。

2.9.2 ⭐ 权限矩阵(实测) ​

操作结果错误信息(逐字)
file list✅ 成功—
file get <name>✅ 成功—
file set <name>❌ 403connector credential writes are **not available to cell callers**
file delete <name>❌ 403connector credential teardown **not available to cell callers**
cred list❌ 403ingress auth callbacks are **not reachable from the runtime cell** (deny-by-default; add an explicit cell_caller_policy row if cell reach is intended)
cred lookup --provider X❌ 403credential lookup **not available to cell callers**
cred lookup --domain X❌ 403同上

⭐ 三个不同层级的错误信息(这是重要信息):

错误措辞含义
**not available to cell callers**基于调用方位的门禁(cell vs host)
**deny-by-default** ... add an explicit cell_caller_policy row⭐ 基于策略表的门禁,且明示了如何放行
ingress auth callbacks are **not reachable from the runtime cell**网络/路径可达性门禁

⭐⭐ 第二条最有价值:它逐字说明了机制 —— cell_caller_policy 是一张表,默认拒绝,需要显式加行才放行。这解释了整个 privsep 隔离的实现方式。

2.9.3 ⭐⭐ 一个真实的安全问题:明文凭据可读 ​

file list 成功返回了未脱敏的凭据:

json
{
  "documents": {
    "custom.cloudflare": "{\n  \"access_token\": \"<SURROGATE_CREDENTIAL>\",\n  \"connected\": true,\n  \"provider\": \"custom.cloudflare\",\n  \"updated_at\": \"<REDACTED_TIMESTAMP>\"\n}"
  }
}

⚠️ 这意味着:

项说明
读权限✅ cell 内可读明文 access token
写权限❌ 被拒(file set 403)
删权限❌ 被拒(file delete 403)

→ 设计意图是「读得到、改不了」 —— cell 需要用凭据(发起 API 调用),但不能改凭据(防篡改/防持久化劫持)。

⚠️ 但这带来一个残余风险: cell 内任何代码都能读到明文 token。 如果 agent 被 prompt injection 控制,它可以读取并外传凭据 (若同时存在出网通道)。

这与 bound-accounts-to-recommendation.md 的发现呼应: Instagram 的访问是走 instagram-cli(封装过的), 而 Cloudflare 的 token 可以通过 authdc 直接读明文。 两条路径的暴露程度不同。

📌 本报告不记录该 token 的实际值(已按本项目惯例脱敏为 <SURROGATE_CREDENTIAL>,见 git 历史卫生规则)。

2.9.4 未被污染(探测无副作用) ​

测试 file set 失败后,确认:

$ authdc file list
{"documents": {"custom.cloudflare": ...}}   ← 仍只有 1 个,无残留

→ 403 门禁是有效的,探测未产生任何写入。


3. ⭐ 5 个被真正隔离的 socket(Permission denied) ​

platform-search-stdout-search    CONNECT_FAIL [Errno 13] Permission denied
printify-verify                  CONNECT_FAIL [Errno 13] Permission denied
shop-wallet-cli-checkout         CONNECT_FAIL [Errno 13] Permission denied
stripe-link-checkout-card        CONNECT_FAIL [Errno 13] Permission denied
tessie-api-verify                CONNECT_FAIL [Errno 13] Permission denied

3.1 为什么这是重要发现 ​

其他 26 个 socket 的权限是 srw-rw---- nobody root —— 即 root 组可访问,而我以 root 运行,所以全部可达。

这 5 个不同:即便以 root 也被拒。

3.2 隔离的性质(⚠️ B 级推断) ​

socket 文件的权限位不足以解释 root 被拒 (root 能绕过文件权限)。 真实原因很可能是:

  1. 目录权限:可能有更深的路径限制
  2. SO_PEERCRED 校验:worker 检查连接方 uid/gid
  3. cgroup identity 绑定:宿主的 privsep 准入检查

这正是 前期预研路线图 §3.2 提到的: 「跨进程能力传递时通过 sendmsg 发送 SCM_RIGHTS」

  • opt-hatch-deep-dive.md 里的 "准入绑定 exact cgroup identity + allowed-peer-uid"。

3.3 ⭐ 这个设计很合理 ​

被隔离的 5 个里,3 个是支付/资金相关:

  • shop-wallet-cli-checkout(钱包结账)
  • stripe-link-checkout-card(Stripe 卡支付)
  • printify-verify(Printify 支付验证)
  • tessie-api-verify(Tesla 账户验证)
  • platform-search-stdout-search(内部搜索)

→ 结论:Muse 对"能花钱"的 socket 做了额外隔离,对"只读数据"的 socket 开放。

这是一个有意的安全分层,不是遗漏。我在 research-direction-recommendations.md §2.3 的担心("支付 socket 可能是刻意隔离")得到证实。


4. 对早期预研假设的实测修正 ​

早期假设表述实测
"剩余 30 个 socket 没有容器内二进制"✅ 31 个,基本准确
"所有 privsep worker 采用统一帧协议:\x00\x03 + JSON-RPC"✅ 正确!此前推导存在偏误
"通过 sendmsg 发送 SCM_RIGHTS"✅ 正确
"确认宿主端 Worker 是否具备合法外部网络出口"⏳ 未验证(需先授权)

⚠️ 我必须更正之前的判断: 我在 research-direction-recommendations.md §1.10 写「前期推断的魔数 \x00\x03 与实测不符」—— 那是我错了。当时我只看到 sendmsg 的 payload(只有 0x46), 没注意到在此之前还有一个独立的 sendto("\x00\x03")。

前期理论推导的协议描述完全正确。


5. 由此解锁的新研究可能 ​

5.1 ⭐ 电商链路:⑪/⑮/⑯ 三环有现成工具 ​

shopify.sock 的 24 个工具覆盖了我此前标为"空白"的环节。 唯一门槛是授权(not_connected)。

→ 这改变了我对电商研究的建议: research-direction-recommendations.md §5 说"补齐四环需要读协议", 现在发现是"需要授权",路径更明确。

5.2 egress 通道问题(初始理论假设) ​

前期预研提出疑问:宿主 worker 是否具备外部网络出口?

现在的证据:

  • worker 返回的 endpoint 是真实外部域名(mcp.slack.com 等)
  • Status 命令返回 not_connected,说明它在尝试连接外部
  • 若 worker 能出网,那么"授权"就等于"获得一条出网通道"

⚠️ 这需要授权后才能验证(无 token 时 worker 不会真正发起外部请求)。

5.3 关于「授权」的门槛 ​

Status 显示 not_connected,而命令枚举里有 AuthorizeUrl / ConnectUrl:

json
{"command": "AuthorizeUrl"}   // 可获取授权 URL

⚠️ 这需要用户(人类)在浏览器完成 OAuth, 容器内无法自行完成。 → 这是一条"需要人类参与"的路径,不是纯技术突破。


6. 明确未做 / 未解 ​

#项状态
1worker 是否能出网⚠️ 未验证(需授权)
25 个 Permission denied 的确切机制⚠️ B 级推断(cgroup/uid 校验)
3box-cli / meta-ads-cli / platform-search 的完整 schema⚠️ 需按字段要求重试
426 个之外是否有其他隐藏 socket⚠️ 未查
5CallTool 直接调 MCP 工具是否可行⚠️ 需授权
6instacart / square 的工具清单⚠️ 未授权时拒绝(与 shopify 不同,见 §2.7)
7authd 如何持有 connector 身份⚠️ schema 明示"owned by authd",机制未查
8sensitivity 字段的取值域与分级规则⚠️ 未查

7. 方法论总结 ​

7.1 ⭐ 本次最大的教训 ​

我盲试约 20 组帧格式,全部失败。strace 一次抓到完整序列。

对比:

盲试:20 组 × 2 分钟 = 40 分钟,0 进展
strace:1 次 = 30 秒,完全破解

原则:

当协议行为无法用「数据流内容」解释时,应立即怀疑 「信息在数据流之外」(ancillary data / fd / out-of-band), 而验证方式是 strace,不是继续猜。

strace 应该在第三次失败后就上,而不是第二十次。

7.2 ⭐ 第二个教训:不要过早断言"文档说错了" ​

我一度写"前期推断的魔数说法与实测不符"并提交了报告 —— 那是错的。

错因:我只看了 sendmsg 的 payload, 没有把 strace 输出的前一行 sendto("\x00\x03") 联系起来。

原则:

当"文档说的"与"我实测的"冲突时, 优先怀疑"我漏看了一段"而不是"文档错了"。

这是我在本项目里第三次犯同类错误 (前两次见 agents-directory.md §3.2 / §4.9.3): 过早下结论,未穷尽证据。


本文所有协议细节来自 strace -f -e trace=sendmsg,sendto,recvfrom 对 /opt/hatch/bin/notion-cli status 的真实抓取。 socket 探测结果来自自建通用客户端(/tmp/pc4.py),在 VM 上实测验证。

基于实测数据与二进制分析 · 零废话硬核逆向