Skip to content

[finding] the runtime dispatcher's /meta LIST reads apply no per-caller gate: through a catch-all host, GET /meta/doc?include=content lists a set-gated doc body, /meta/book lists a set-gated book, /meta/app lists gated apps and entries #20237

Description

@objectstack-fleet

Filing gate: ① a defect with a named landing site, packages/runtime/src/domains/meta.ts handleMetadataRequest's one-segment LIST branch (parts.length === 1: protocol.getMetaItems → slimDocList, about :1039-:1080). Finding class (a), under the security exception: it exposes data. reach: was measured through dispatch(), the createHonoApp catch-all's delegate.

Found by the os-dev round on #20193 (PR #20236), which gates the dispatcher's ITEM reads and left the LIST branch untouched. That branch is outside its claimed surface, and it needs RestServer's LIST filters extracted as a second seam. Filed by the domain:cli execution seat (#6024, session_01UYBdGBzWSrAMzpW8ah3GbP). ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.

The reader who acts is the domain:cli execution seat: packages/runtime and packages/rest are both this lane's. It builds on PR #20236's shared gate module and dispatches after that PR lands.

Dedupe: MCP issue search in this repository, open and closed, run 2026-09-27, 「runtime dispatcher meta list branch getMetaItems no per-caller filter doc include content book app requiredPermissions leak」 → 3 hits. #20193 (open) is the ITEM half of the same family, which PR #20236 closes. #20130 (closed duplicate) was the RestServer alternate doors. #4698 is unrelated. None covers the list branch.

What happens (measured by the #20193 dev through dispatch(), head 0fcb064a2)

An authenticated caller who does not hold crm_admin sends:

request dispatcher answer RestServer's GET /meta/:type answer to the same caller
GET /meta/doc?include=content 200, lists crm_admin_runbook with its body lists [crm_intro] only
GET /meta/book 200, lists the set-gated admin_guide with its description []
GET /meta/app 200, lists payroll (app-level requiredPermissions) and crm with the gated nav_finance_ledger [crm], pruned

⚠️ These readings are the dev's, relayed. The seat confirmed at source on origin/main that the list branch reads protocol.getMetaItems and renders through slimDocList with no audience, requiredPermissions or app-filter spelling (about :1039-:1080). The seat did not re-drive the requests.

The contract it contradicts

  • ADR-0046 §6.7: docs content is gated server-side at the doc and book reads.
  • content/docs/ui/apps.mdx's requiredPermissions row: 「absent from the /meta body」.
  • AGENTS.md "Route & surface ownership": this is a second transport answering the same /meta read with different rules.

Direction (for the claimant, ⛔ not a ruling)

Follow #20193's route: extract RestServer's LIST filters (the doc and book audience prune, the app nav filter, the dashboard widget gate and the ADR-0106 object mask on the list) as one transport-neutral seam beside PR #20236's meta-item-read-gate.ts, and have the dispatcher's list branch call it. ⛔ No second audience resolver: ruling 5793362670 item 1.

Pin: each of the three rows above, driven through a composed catch-all host, answers what RestServer answers the same caller. A holder is the control.

Seam

spec:AppSchema.requiredPermissions / spec:BookSchema.audience → runtime:packages/runtime/src/domains/meta.ts handleMetadataRequest (parts.length === 1)

Dedupe words: dispatcher meta list audience · handleMetadataRequest list include=content leak · createHonoApp meta app list requiredPermissions · catch-all meta list ungated


Generated by Claude Code

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

    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsbugSomething isn't workingdomain:clipriority:p1High: required for production / M2security

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions