Skip to content

finding: /packages 域整体没有授权判据 —— discard-drafts(破坏性)、export、GET /packages 零能力调用方均实测 200,#7023 只是其中一条 #7033

Description

@os-project-manager

由 #7023 的只读普查顺带量出(PD #10 另立卡,不在那条卡里修)。#7023 记的是 POST /packages/:id/publish-drafts 一条路由;本卡记的是它所在的整个域没有授权这一结构事实 —— publish-drafts 只是最先被看见的那一条。

结构事实(实测)

  • packages/runtime/src/domains/packages.ts 全文 739 行,授权判据命中数为 0。
  • /packages 不在 authz-conformance.matrix.ts 的任何条目里。
  • /packages 域没有 shouldDenyAnonymous;而 /meta、/actions、/automation、/ai、/security 五个域都有。

第三条的后果比「零能力」更强一档:走完整 dispatch() 管线、连 userId 都没有(身份解析产出 principalKind:'guest')的调用方,publish-drafts 仍得 200。

四条实测路由(调用方 {userId:'u_portal', systemPermissions:[]},零能力已认证)

路由 实测 性质
POST /packages/:id/discard-drafts 200,discardPackageDrafts 被调用 破坏性 —— 丢掉该 package 名下每一条 pending draft
GET /packages/:id/export 200 整包读出,27 种 metadata 类型
GET /packages 200 package id 枚举面
POST /packages/:id/publish-drafts 200,目标函数被调用 已由 #7023 记录

对照组(同一调用方、同一次运行):POST /metadata/_migrate-stored 得 403,且目标函数一次没进(信封 {code:'PERMISSION_DENIED', httpStatus:403})。所以这不是「平台还没有能力门」,而是同一套机制在隔壁域用了、在这个域没用。

为什么值得作为一条卡而不是四条

四条共用同一个根因(域级无授权 + 不在 conformance matrix 里)和同一个修法(补域级判据 + 补 matrix 条目)。拆成四条会让四个 PR 各自在 packages.ts 里加一段形状略有差异的门 —— 这正是 #6345 / #6969 反复在收口的那种发散。

另注 GET /packages 是这条链的第一步:枚举出 id 之后,export / discard-drafts / publish-drafts 都不需要任何 UI 即可到达。单独看是「只读列表」,合起来看是攻击链入口。

⛔ 不预设门的选择

维护者对 #7023 的现行指令是先普查、不落门。本卡同样不选门,只记录实测。#7023 上已给出三条候选门各自会 403 掉谁的实测对照,那份分析对本卡四条路由同样适用(同域同调用方)。

已知覆盖缺口

cloud 仓在普查会话中未挂载(add_repo objectstack-ai/cloud 两次被拒,22:27Z 与 05:2xZ),因此调用方普查不覆盖该仓。任何门的决定都继承这个缺口 —— 落门前应先在 cloud 里补一次调用方普查,否则可能 403 掉未知调用方。

关联

#7023(同域 publish-drafts,target:v17,本卡的来源)· ADR-0045(发布门)· authz-conformance.matrix.ts · packages/runtime/src/domains/meta.ts 的 shouldDenyAnonymous 与路由级 manage_metadata 门(可照抄的先例)

给 triage 的提示:#7023 是 target:v17。本卡与它同根因,维护者可能希望把它一并拉进 v17 —— 但本席不擅自扩大 v17 范围,故未加该标签。

未实测(勿当事实引用)

  • 真实 server 全中间件下,匿名请求是否会被更前面的中间件拦掉(普查用的是 dispatch() 管线,不是完整 server)。
  • discardPackageDrafts 真实落库的删除行数(测试 double 缺 metadata.getObject)。

Activity

  1. os-project-manager commented on Aug 9, 2026

    @os-project-manager
    CollaboratorAuthor

    Triage (maintainer-authorized one-off pass #2, 2026-08-09, registered on #6015): promoted finding → pm:queue, target:v17 applied (board class ① — a shipped security hole: a guest-principal caller gets 200 on a destructive route today). An entire routed domain with zero authorization predicates, absent from the authz conformance matrix, and without the shouldDenyAnonymous floor its five sibling domains all have is a structural gap, not a per-route bug — #7023 (queued, boarded) covers the single worst route; this card is the domain-level fix: capability predicates per route, matrix enrollment, and the anonymous floor. Implementation should land #7023's route inside this card's frame rather than twice.


    Generated by Claude Code

  2. os-project-manager commented on Aug 9, 2026

    @os-project-manager
    CollaboratorAuthor

    认领(dev agent)

    开始实现前已重读 #7033 与 #7023 全部评论,未见其它 session ID 的更早认领。


    Generated by Claude Code

  3. os-project-manager commented on Aug 9, 2026

    @os-project-manager
    CollaboratorAuthor

    续做(接力,同 session)


    Generated by Claude Code

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

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions