Skip to content

[test-gap][control-plane] 控制面 0600 socket 缺少「第二主体拒绝」E2E(AGENT.md §6 规则3 MUST;验收矩阵自标 ❌ gap 跨轮未落地) #180

Description

@jamiesun

背景

AGENT.md §6「验收矩阵硬规则」规则 3(MUST 级)要求:每个“触及权限”的能力必须以至少两个主体/角色验证。对 Subnetra 而言唯一权限面是 0600 的 UDS 控制 socket,“两个角色”= socket 属主 vs. 任意其他主体(非属主 uid)

docs-site/en/src/reference/roadmap.md 的 Capability Coverage Matrix 自身把这一项标为 ❌ gap

  • 「Policy engine & zero-downtime route updates (RCU)」Role coverage(roadmap.md:108):Partial — 0600 socket binding asserted (src/uds.zig, #37); a second-principal denial E2E is a ❌ gap
  • 「Observability」同一 UDS 0600 注记(roadmap.md:111)
  • 矩阵「Minimum expectation for each open gap」明确给出最小测试(roadmap.md:116-117):一个 E2E 步骤,证明非属主 uid 在 live 控制 socket 上得到 EACCES(owner vs. non-owner = 两个角色)。

证据(机制已到位——这是测试欠账,非现网漏洞)

  • src/uds.zig:247-262:bind 前 umask(0o177),bind 后 Linux fchmod(fd, 0o600) / macOS chmod(path, 0o600),TOCTOU-free 地把节点钉成 0600(defense-in-depth)。
  • src/uds.zig:979-999:单元测试 "openDgramSocket: control socket is bound 0600 regardless of umask (#37)" 断言 mode & 0o777 == 0o600。这是属主视角的正向机制断言。

缺口:没有任何测试从“第二主体”(非属主 uid)视角验证访问被拒——

  • test/integration/run.sh(755 行)唯一与控制 socket 相关的鲁棒性断言在 :645-647,是数据面存活断言(hub 吸收 40 个敌意 UDP 报文后未崩溃、“kept serving its control socket”),与授权无关。
  • 全仓 grep -rniE "seteuid|setreuid|getuid|geteuid|EACCES|EPERM|non-owner|second principal" src test tools。无非属主/降权访问 socket 的用例。

预期 vs 实际

  • 预期(§6 规则3 + 矩阵最小期望):一个 E2E 步骤,以非属主 uid 连接/发命令到 live 控制 socket,断言得到 EACCES(属主可正常操作作为对照)。
  • 实际:只有属主视角的 0600 单元断言;两主体 E2E 缺失,矩阵自标 ❌ gap

影响范围

  • 治理:§6 规则3 为 MUST 级、“不得弱化/推迟/降级为建议”。该 MUST 自 docs: mandate a Capability Coverage Matrix as the roadmap acceptance chapter #176(矩阵落地,即当前 HEAD 9c9a6fa)起以已知 gap 状态携带,事实上处于 deferred。
  • 安全保障0600 是产品唯一权限边界。机制虽在且有单元断言,但缺少“其他主体确实被拒”的端到端回归护栏;未来若 uds bind/权限逻辑回归到 0666,现有测试无法在两主体维度捕获。
  • 仅限测试完整性,不改变现网行为。

建议(最小落地)

test/integration/run.sh 增一个 E2E 步骤(复用其 netns 夹具):

  1. 属主启动 daemon、bind 0600 控制 socket;属主 subnetra … status/policy show 成功(正向对照)。
  2. 以非属主 uid(如 nobody,经 ip netns exec … setpriv --reuid nobody --regid nogroup --clear-groups … 或等价降权)对同一 socket 发 status/policy show,断言被拒(connect/sendto 返回 EACCES/EPERM;客户端非 0 退出且无回包)。
  3. 断言 daemon 侧路由树/状态未因被拒尝试改变(复用既有 policy show 快照对照)。
  4. 落地后把 roadmap.md 矩阵对应两行 Role coverage 从 ❌ gap 更新为证据路径(§6 规则5:能力随 E2E + 矩阵行落地)。

macOS 无 netns 且 AF_UNIX 权限语义不同,可将该 E2E 限定为 Linux integration job;平台差异在矩阵证据里注明即可。

严重度

Low(测试完整性/治理欠账,非现网漏洞),但为 AGENT.md §6 MUST 级义务且触及唯一权限面,建议优先补齐。

评审记忆自 review #4(2026-09-03)记为观察项 W3,review #5(2026-09-07)确认自 #176 起跨轮零代码改动后按预设规则升级为本 issue。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent-todoReady for automated agent implementationpriority: P2Depends on earlier work / verificationsecuritySecurity hardening or vulnerability

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions