Repository navigation
Description
由 #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
os-project-manager commentedon Aug 9, 2026
Triage (maintainer-authorized one-off pass #2, 2026-08-09, registered on #6015): promoted
finding→pm:queue,target:v17applied (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 theshouldDenyAnonymousfloor 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
os-project-manager commentedon Aug 9, 2026
认领(dev agent)
session_017uFVNMmTxLpmfQYiuKM1Yxclaude/issue-7033-packages-authz/packages域整体没有授权判据 ——discard-drafts(破坏性)、export、GET /packages零能力调用方均实测 200,#7023 只是其中一条 #7033(主)与 finding:POST /packages/:id/publish-drafts整包 draft 批量转正,零能力的已认证调用方即可调用(实测 200 vs 同族_migrate-stored403) #7023 合并为一个 PR 关闭两者(同域同根因)。落地维护者 2026-08-09 已裁的门:写/破坏性路由要求manage_metadata;读路由域级补shouldDenyAnonymous+ D4 读豁免集{studio.access, setup.access}。开始实现前已重读 #7033 与 #7023 全部评论,未见其它 session ID 的更早认领。
Generated by Claude Code
os-project-manager commentedon Aug 9, 2026
续做(接力,同 session)
session_017uFVNMmTxLpmfQYiuKM1Yx(与既有认领同一 session)claude/issue-7033-packages-authz,从 PM 的 wip checkpoint97c875715续做/packages域整体没有授权判据 ——discard-drafts(破坏性)、export、GET /packages零能力调用方均实测 200,#7023 只是其中一条 #7033 / finding:POST /packages/:id/publish-drafts整包 draft 批量转正,零能力的已认证调用方即可调用(实测 200 vs 同族_migrate-stored403) #7023 全部评论,未见其它 session ID 的更早认领。Generated by Claude Code
feat(runtime,rest): /packages 域补齐授权门 —— 写要 manage_metadata、读要 D4 读集、全…
feat(runtime,rest): /packages 域补齐授权门 —— 写要 manage_metadata、读要 D4 读集、全…
feat(runtime,rest): /packages 域补齐授权门 —— 写要 manage_metadata、读要 D4 读集、全…
fix(metadata-core): derive the ADR-0106 D4 read exemption from the ob…
fix(runtime): refuse to disable or delete a read-only package (object…