You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[read-scope-sql] unsafe field identifier "secret_policy_field" — refusing to build read scope (fail-closed).
[read-scope-sql] unsupported operator "$regex" on "owner_email" (fail-closed).
[read-scope-sql] "approved_by_manager" has a nested/relation value which is not supported in a read scope (fail-closed).
ECHOED [read-scope-sql] unsafe field identifier "owner id" — refusing to buil…
ECHOED [read-scope-sql] unsafe alias identifier "crm opportunity" — refusing …
ECHOED [read-scope-sql] read scope must be a filter object (fail-closed).
ECHOED [read-scope-sql] "$and" requires an array (fail-closed).
ECHOED [read-scope-sql] unsupported top-level operator "$nor" (fail-closed).
ECHOED [read-scope-sql] bare array value for "region" — use { $in: [...] } (f…
ECHOED [read-scope-sql] "owner" has a nested/relation value which is not supp…
ECHOED [read-scope-sql] $in for "region" needs an array (fail-closed).
ECHOED [read-scope-sql] $nin for "region" needs an array (fail-closed).
ECHOED [read-scope-sql] $between for "amount" needs [min,max] (fail-closed).
ECHOED [read-scope-sql] unsupported operator "$regex" on "owner" (fail-closed…
现状
#5367(维护者 2026-08-06 裁决,方案 B)把
read-scope-sql.ts的十处 fail-closed 拒收改成READ_SCOPE_COMPILE_FAILED/ 500,并让POST /analytics/dataset/querywithhold 任何声明了服务端故障(status >= 500且带code)的生产方 message。理由之一是这些 message 点名 RLS 策略的字段名与比较值:这些内容来自管理员写的 sharing rule / permission set,由 security 服务编译后经
getReadScope交给 analytics —— 调用方(租户)从来没写过它们,也不该能从错误体里读出来。同一批拒收在姐妹面上没有被堵。
/analytics/query经dispatcher-plugin.errorResponseBase(packages/runtime/src/dispatcher-plugin.ts:445)退出,它的 message 判据是:而
looksLikeInternalErrorLeak(packages/types/src/error-leak.ts:47)是对 SQL/驱动措辞 的启发式(sqlite_、SQLSTATE、以SELECT/INSERT INTO/UPDATE/DELETE FROM开头、constraint failed/unique constraint/foreign key)。实测把上面十一种 message 形态逐条喂进去:11/11 全部 ECHOED —— 即
errorResponseBase会把策略内容原样写进error.message,状态码是 500(err.status被采纳)但正文没有被收口。read-scope-sql.ts的compileScopedFilterToSql在NativeSQLStrategy.applyReadScope与ObjectQLStrategy的回显 SQL 两条路上都会跑,而这两条路都服务/analytics/query,所以这条面是真实可达的,不是理论问题。为什么没在 #5367 里一起做
#5367 的题目是 dataset 路由那串 message 正则名单的退休。这条泄漏在本单之前就存在、且在另一条路由上,把它一起改会把一次可见行为变更(该面 message 从可读变为收口)夹带进一个以「退休正则名单」为题的 PR。按 PD #10 单独立项。
PR #5808(#5367 的第二个 PR)里的规则是就地写在
rest-server.ts③ 分支内的三行判断,故意没有抽成共享谓词 —— 只有一个消费者时提升就是推测性面。本单是第二个消费者出现的时刻。建议方向(不预判)
@objectstack/types里与looksLikeInternalErrorLeak同居的一个小谓词 —— 例如declaresServerFault(err)(status >= 500且有非空code)—— 然后两个边界(rest-server.ts的 analytics dataset ③ 分支、dispatcher-plugin.errorResponseBase)都读它。error-leak.ts的文件头本来就写着「‘不要把内部细节发给客户端’是 HTTP 边界的属性,不是某个 router 的属性,所以谓词放在这里」,这正是它说的那种情况。errorResponseBase内联同样的判断。省事,但两处实现一条规则,是 Envelope drift is not just service-storage: four more route modules emit bare bodies, two of them the pre-#3675{ error: '<string>' }#3843/analytics /query 未做 cube 存在性校验,未注册名直达驱动当表名;且错误路径原样回显驱动 SQL(#3770 同类,另一子系统) #3867 反复付过学费的形状。looksLikeInternalErrorLeak教会认[read-scope-sql]。不建议 —— 那是往回加措辞嗅探,与 analytics 的 filter 拒收到不了调用方:service 侧多数拒收没有 ADR-0112 信封,REST 面又用 message 正则嗅探,一律答 500 #5352/analytics dataset 路由的 message 正则兜底没有退休时间表:六族拒收仍靠措辞分类,改一个字就换一个 HTTP 码 #5367 刚清掉的机制同族。无论选哪个都要注意不能把 withhold 放宽到「所有 5xx」:#5667 刻意保留了未声明 5xx 的可读性(自产故障 "no strategy can handle query …" 应当照旧可读),PR #5808 的用例两侧都钉了这一点,新实现要沿用。
验收建议
/analytics/query面加端到端用例:read-scope 拒收 → 500,error.message为Internal server error,body 不含策略字段名,error.details.code为READ_SCOPE_COMPILE_FAILED(errorResponseBase已经会把err.code放进details,The dispatcher puts the HTTP status inerror.codeand parks the real code indetails— pinned in #3687, still unfixed #3842),完整原文在日志/errorReporter 侧。参考
packages/runtime/src/dispatcher-plugin.ts:445(errorResponseBase)、:468-:472(message 判据)、:480-:483(details.code)packages/types/src/error-leak.ts:47(looksLikeInternalErrorLeak)及其文件头关于「边界属性」的表述packages/services/service-analytics/src/read-scope-sql.ts(十处拒收 +readScopeCompileError)