Skip to content

fix(security): getReadFilter 对 on-behalf-of 读 fail-closed 哨兵(#2852 Gap 1 潜伏面) - #2988

Merged
os-zhuang merged 1 commit into
mainfrom
claude/nice-tesla-jpzls8
Jul 15, 2026
Merged

fix(security): getReadFilter 对 on-behalf-of 读 fail-closed 哨兵(#2852 Gap 1 潜伏面)#2988
os-zhuang merged 1 commit into
mainfrom
claude/nice-tesla-jpzls8

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

目的

关闭 #2852 剩余的 Gap 1 的潜伏面(Gap 2 /analytics/query 无 context 已在 #2956 修复)。getReadFilter——analytics/raw-SQL 路径绑定的 read-scope 提供者——只解析调用方自身 ceiling;engine middleware 对 find/count/aggregate 施加的 ADR-0090 D10 delegator RLS 交集resolveDelegatorContextsecurity-plugin.ts:689)在这条路径上缺位。因此对一个 delegated(onBehalfOf)上下文在这里算 filter 会静默放宽到 agent 自身(更宽)的 scope,正是 D10 在 CRUD 路径上防住的 confused-deputy 放宽。

改动(哨兵,非完整交集)

getReadFiltercontext.onBehalfOf.userId 存在时 fail-closed:返回 RLS_DENY_FILTER + 响亮 error 日志,而不是 under-scope。与该函数已有的 fail-closed 风格(解析失败分支)一致。

  • system on-behalf-of 豁免isSystem 短路在哨兵之前(engine 自调用不被拒)。
  • 当前无 live 流量:OAuth agent 只能到 /mcp,不暴露 analytics——这是潜伏不变量守卫,不是 live 行为变更。把「将来某人把 analytics 桥进 agent 面时静默放宽」提前变成「显式拒绝 + 报错」。

为什么是哨兵而非完整交集

完整修复要把 delegator 交集下沉进 computeRlsFilter/共享 helper(单缝,避免复制 middleware↔service 分叉),而 #2920 B1(租户隔离拆 Layer 0,ADR-0095 D1)会重构同一条缝。现在精雕会与 B1 冲突/白做,故只落 fail-closed 哨兵,完整交集随 B1(issue #2852 已记录两档计划)。

验证

  • @objectstack/plugin-security441 passed(新增 2:delegated context → deny sentinel + 日志;system on-behalf-of → 豁免放行)
  • turbo build(plugin-security + deps)✓ · ESLint(改动文件)✓ · changeset:plugin-security patch

关联

#2852(read-scope D10 缺口,Gap 2 已修)· ADR-0090 D10 · #2920 B1 / ADR-0095 D1(computeRlsFilter 重构缝,完整交集落点)· #2949(explain-vs-enforcement 分叉先例)

🤖 Generated with Claude Code

https://claude.ai/code/session_012RE5oFswe4DUvExuAgvbg2


Generated by Claude Code

…Filter (#2852)
getReadFilter — the read-scope provider the analytics/raw-SQL path binds
to — resolves only the caller's own ceiling; the ADR-0090 D10 delegator
RLS intersection that the engine middleware applies to find/count/
aggregate is absent on this path. Computing a filter here for a delegated
(on-behalf-of) context would silently widen the read past the delegator's
scope — the confused-deputy widening D10 prevents on the CRUD path.
Until the intersection is threaded through computeRlsFilter (tracked with
#2920 B1 / ADR-0095 D1), deny fail-closed (deny sentinel + error log) when
context.onBehalfOf.userId is set. System on-behalf-of bypasses ahead of
the guard; no agent surface reaches analytics today, so this is a
latent-invariant guard, not a live-traffic change.
Tests: 2 new getReadFilter cases (delegated context → deny sentinel +
logged; system on-behalf-of → bypass). plugin-security 441 passed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RE5oFswe4DUvExuAgvbg2
@vercel

vercelBot commented Jul 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specBuildingBuildingPreview, CommentJul 15, 2026 4:02pm

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling size/s labels Jul 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/plugin-security.

11 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/getting-started/cli.mdx(via @objectstack/plugin-security)
  • content/docs/permissions/access-recipes.mdx(via packages/plugins/plugin-security)
  • content/docs/permissions/authorization.mdx(via packages/plugins/plugin-security)
  • content/docs/permissions/explain.mdx(via @objectstack/plugin-security)
  • content/docs/permissions/permissions-matrix.mdx(via packages/plugins/plugin-security)
  • content/docs/permissions/sharing-rules.mdx(via @objectstack/plugin-security)
  • content/docs/plugins/index.mdx(via @objectstack/plugin-security)
  • content/docs/plugins/packages.mdx(via @objectstack/plugin-security)
  • content/docs/releases/implementation-status.mdx(via @objectstack/plugin-security)
  • content/docs/ui/audience-based-interfaces.mdx(via packages/plugins/plugin-security)
  • content/docs/ui/dashboards.mdx(via @objectstack/plugin-security)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang marked this pull request as ready for review July 15, 2026 16:30
@os-zhuang
os-zhuang merged commit 93bb7b4 into mainJul 15, 2026
15 of 16 checks passed
@os-zhuang
os-zhuang deleted the claude/nice-tesla-jpzls8 branch July 15, 2026 16:30
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/steststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-zhuang@claude