Skip to content

GET /meta/books/:name(复数拼写)绕过 ADR-0046 §6.7 audience 门禁 —— 缓存分支的 doc/book 排除写的是字面量比较 #6241

Description

@qq9340100

发现于 #5881 的实施测量(旁证,与该单改动无关 —— 改前改后同样成立)。基线 origin/main @ 8e2bbba24

事实

packages/rest/src/rest-server.ts:4249 的缓存分支进入条件,对 doc / book 的排除写的是字面量比较:

if (metadata.enableCache && p.getMetaItemCached && !isAppType && !isDraftRead && !previewDrafts
    && !packageScoped && req.params.type !== 'doc' && req.params.type !== 'book') {

而同一 handler 里 app 用的是归一化后的 RestServer.metaTypeSingular(req.params.type) === 'app'PLURAL_TO_SINGULAR(packages/spec/src/shared/metadata-collection.zod.ts:144-145)含 docs: 'doc' / books: 'book',元数据路由两种拼写都受理,且 Prime Directive #3 规定复数才是 REST 的规范拼写(/api/v1/meta/books)。

于是 GET /api/v1/meta/books/:name 进入缓存分支,而 §6.7 audience 门禁只写在 else(非缓存)分支里(rest-server.ts:4390-4434)—— 门禁一次都不跑。enableCache 默认为 true

这正是 metaTypeSingular 自己的 docstring 记下的 #3984 那一类缺陷("the plural spelling cannot fall outside it"),在同一个文件里换了个位置复发。

实测

RestServer,默认配置(不写 metadata 块 ⇒ enableCache 取默认 true),protocol 同时提供 getMetaItemgetMetaItemCached;book 声明 audience: { permissionSet: 'ps_admin' };调用方已登录但不持有任何 permission set:

singular "book" :: cachedCalls=0 status=[403] body={"error":"This documentation is limited to holders of a permission set you do not have","code":"PERMISSION_DENIED"}
plural  "books":: cachedCalls=1 status=[]    body={"type":"book","name":"admin_guide","item":{"name":"admin_guide","audience":{"permissionSet":"ps_admin"},"title":"Admin Guide"}}

同一个 book,同一个调用方:单数拼写 403,复数拼写 200 并原样送出正文。

(探针脚本一次性,未提交。)

影响

  • ADR-0046 §6.7 的 audience 授权在规范拼写上失效:{ permissionSet } 门禁的 book(如 Admin Guide)会送给不持有该 set 的已登录调用方;org book 在对匿名开放的部署上同理(匿名分支由 umbrella gate 决定可达性,授权本应留给 handler 的 §6.7 门禁 —— 而它没跑)。
  • doc 同款:GET /meta/docs/:name 走同一条路。
  • app 的处置不对称:app 用归一化比较,doc/book 用字面量比较,两者在同一个 if 里。

可能的处置(未定,交分诊)

把两处字面量比较换成 metaTypeSingular(...) 归一化后的比较(与 isAppType 同款)。#5881 的修复已把 dashboard 的排除写成归一化形式,可直接照抄该形状。

需要注意这不是纯粹的一行改动:换成归一化后,docs/books 复数读取会从缓存分支移到非缓存分支,ETag 快路径随之消失(与 #5881dashboard 的取舍同源),现有测试若有钉复数缓存行为的需要重判。

关联:#5881(在其实施中测得,互不阻塞)、#3984(同类缺陷的前身)、ADR-0046 §6.7。

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions